- 左操作数是一个指向有const限定符的char的指针 (const是用来修饰char类型的,并不是修饰*指针类型的)
- 右操作数是一个指向没有限定符的char的指针
- char类型与char类型是相容的,左操作数所指向的类型具有右操作数所指向类型的限定符(其实没有),在加上自身的限定符(const)
fprintf(stderr, "-1 < (unsigned int)1)\n");
} else {
fprintf(stderr, "-1 > (unsigned int)1)\n");
}
if (-1 < (unsigned char)1) {
fprintf(stderr, "-1 < (unsigned char)1)\n");
} else {
fprintf(stderr, "-1 > (unsigned char)1)\n");
}
-1 < (unsigned char)1) // -1类型不动,仍然是int类型,(unsigned char)1被提升到int类型
int b[] = {3, 4};
array ab = {&a, &b};
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#define MAXTOKENS 100
#define MAXTOKENLEN 64
enum type_tag { IDENTIFIER, QUALIFIER, TYPE };
struct token {
char type;
char string[MAXTOKENLEN];
};
int top = -1;
struct token stack[MAXTOKENS];
struct token this;
#define pop stack[top--]
#define push(s) stack[++top] = s
enum type_tag classify_string()
{
char* s = this.string;
if (!strcmp(s, "const")) {
strcpy(s, "read-only");
return QUALIFIER;
}
if (!strcmp(s, "volatile")) return QUALIFIER;
if (!strcmp(s, "void")) return TYPE;
if (!strcmp(s, "char")) return TYPE;
if (!strcmp(s, "signed")) return TYPE;
if (!strcmp(s, "unsigned")) return TYPE;
if (!strcmp(s, "short")) return TYPE;
if (!strcmp(s, "int")) return TYPE;
if (!strcmp(s, "long")) return TYPE;
if (!strcmp(s, "float")) return TYPE;
if (!strcmp(s, "double")) return TYPE;
if (!strcmp(s, "struct")) return TYPE;
if (!strcmp(s, "union")) return TYPE;
if (!strcmp(s, "enum")) return TYPE;
return IDENTIFIER;
}
void gettoken()
{
char* p = this.string;
while ((*p = getchar()) == ' ') ;
if (isalnum(*p)) {
while (isalnum(*++p = getchar()));
ungetc(*p, stdin);
*p = '\0';
this.type = classify_string();
return ;
}
if (*p == '*') {
strcpy(this.string, "pointer to");
this.type = '*';
return ;
}
this.string[1] = '\0';
this.type = *p;
return;
}
void read_to_first_identifier()
{
gettoken();
while (this.type != IDENTIFIER) {
push(this);
gettoken();
}
printf("%s is ", this.string);
gettoken();
}
void deal_with_arrays()
{
while (this.type == '[') {
printf("array ");
gettoken();
if (isdigit(this.string[0])) {
printf("0..%d ", atoi(this.string) - 1);
gettoken();
}
gettoken();
printf("of ");
}
}
void deal_with_function_args()
{
while (this.type != ')') {
gettoken();
}
gettoken();
printf("function returning ");
}
void deal_with_pointers()
{
while (stack[top].type == '*')
{
printf("%s ", pop.string);
}
}
void deal_with_declarator()
{
switch (this.type) {
case '[' :
deal_with_arrays(); break;
case '(' :
deal_with_function_args(); break;
}
deal_with_pointers();
while (top >= 0) {
if (stack[top].type == '(') {
pop;
gettoken(); // read chars after ')'
deal_with_declarator();
} else {
printf("%s ", pop.string);
}
}
}
int main(int argc, char** argv)
{
read_to_first_identifier();
deal_with_declarator();
printf("\n");
return 0;
}
譬如输入“const char* (*p[])(int);”, 它会告诉你:“p is array of pointer to function returning pointer to char read-only”。(cute?)
指针 | 数组 |
保存数据的地址 | 保存数据 |
间接访问数据,首先取得指针的内容,把它作为地址,然后从这个地址提取数据。 如果指针有一个下标[i],就把指针的内容加上i作为地址,从中提取数据 |
直接访问数据,a[i]只是简单的以a+i为地址取得数据 |
通常用于动态数据结构 | 通常用于存储固定数据且数据类型相同的元素 |
通常指向匿名数据 | 自身即为数据名 |
实参 | 所匹配的形式参数 |
数组的数组 char c[8][10] | char (*)[10]; 数组指针 |
指针数组 char *c[15]; | char **c; 指针的指针 |
数组指针(行指针) char (*c)[64] | char (*)[64]; 不改变 |
指针的指针 char** c; | char** c; 不改变 |
#define random(x) (rand() % x) //产生x内的随机函数
#define RAND_N 1000
//自定义随机器
void my_random(char *buf1, char *buf2, int count)
{
//判断范围
if(random(RAND_N) < RAND_N / count)
{
strcpy(buf1, buf2);
}
}
//主函数
int main()
{
FILE *fp;
int count = 0;
char buf1[100], buf2[100];
if ((fp = fopen("d:/test.txt", "r")) == NULL) {
fprintf(stderr, "open error");
exit(0);
}
if(fscanf(fp, "%s", buf1) == EOF)
{
printf("file is null\n");
return 0;
}
count++;
srand((int)time(0));//设置随机数种子,srand不能调用两次以上
for(count++; fscanf(fp, "%s", buf2) != EOF; count++)
{
my_random(buf1, buf2, count);
}
fclose(fp);
printf("随即读取的字符串为 : %s\n", buf1);
return 0;
}