使用此代码,我可以将字符串存储到namesArray中并将其打印到屏幕上。如果namesArray是int?
的指针,这怎么可能呢?int numNames = getMaxNames(argv[1]);
int* namesArray = malloc(numNames * sizeof(int));
int i;
for (i = 0; i< numNames; i++) {
scanf("%s", &namesArray[i]);
}
for (i = 0; i< numNames; i++) {
printf("%s\n", &namesArray[i]);
}
答案 0 :(得分:2)
您可以通过编写
来调用undefined behavior scanf("%s", &namesArray[i]);
其中,&namesArray[i]
的类型为int *
。
引用C11
,章节§7.21.6.2,fscanf()
(强调我的)
s
匹配一系列非空白字符。 286) 如果不存在l长度修饰符,相应的参数应为a 指向大小足以接受的字符数组的初始元素的指针 序列和终止空字符,将自动添加。
和
[...]除非用*表示分配抑制,否则 转换结果放在下面第一个参数指向的对象中 尚未收到转换结果的format参数。 如果是这个对象 没有合适的类型,或者无法表示转换结果 在对象中,行为未定义。
那就是说,在使用返回的指针之前,你真的应该检查malloc()
的成功。
答案 1 :(得分:0)
C不关心指针是什么。如果sizeof(char)为1,而sizeof(int)为4,则malloc(sizeof(int))与malloc(sizeof(char)* 4)相同。注意malloc无论如何都返回一个void *。由于C并不真正关心指针是什么,所以你总是可以只是转换缓冲区,它不会抱怨。另外请注意,你可以在类型之间进行牛仔风格的演绎而且C不关心,但它并不是很好的形式,许多编译器会抱怨它。
所以请考虑以下代码:
char* str = (char*)malloc(sizeof(char)*4);
int* intArr = (int*)malloc(sizeof(int));
//it is perfectly legal to do this:
char* intStr = (char*)intArr;
//or
printf("int char %c\n", ((char*)intArry)[2]);
//or
printf("int char %c\n, intStr[2]);
//or
printf("int char %c\n, intStr+2);
//or copy intArr into str
for (int i = 0; i < 4; i++) {str[i] = ((char*)intArr)[i];}
话虽如此,除非你真的知道指针是如何工作的以及你在做什么,否则你应该实际做这种事情。确保您出于正确的原因这样做。因为它似乎工作不正确的原因。 :)
因此,对于您的代码,您可以像这样“修复”它,但这段代码仍然“非常糟糕”。 scanf不安全。它很容易溢出你的namesArray缓冲区。
int numNames = getMaxNames(argv[1]);
char* namesArray = (char*)malloc(numNames * sizeof(int));
int i = 0;
for (i = 0; i< numNames; i++) {
scanf("%s", namesArray);
}
for (i = 0; i< numNames; i++) {
printf("%s\n", namesArray);
}
` OR
int numNames = getMaxNames(argv[1]);
int* namesArray = (int*)malloc(numNames * sizeof(int));
int i = 0;
for (i = 0; i< numNames; i++) {
scanf("%s", (char*)namesArray);
}
for (i = 0; i< numNames; i++) {
printf("%s\n", (char*)namesArray);
}