C-静态字符数组与动态字符数组
此代码编译时带有警告,但会打印输入字符串:C-静态字符数组与动态字符数组,c,arrays,string,dynamic,static,C,Arrays,String,Dynamic,Static,此代码编译时带有警告,但会打印输入字符串: char staticArray[100]; scanf("%s",&staticArray); printf("%s\n", staticArray); 警告:format指定类型“char*”,但参数的类型为“char(*)[100]'[-Wformat] 此代码也会编译为警告,但会引发分段错误: char* dynamicArray; dynamicArray = (char*) malloc(sizeof(char)*100); sc
char staticArray[100];
scanf("%s",&staticArray);
printf("%s\n", staticArray);
警告:format指定类型“char*”,但参数的类型为“char(*)[100]'[-Wformat]
此代码也会编译为警告,但会引发分段错误:
char* dynamicArray;
dynamicArray = (char*) malloc(sizeof(char)*100);
scanf("%s", &dynamicArray);
printf("%s\n", dynamicArray);
警告:format指定类型“char*”,但参数的类型为“char**”[-Wformat]
我知道这两个都是错误的,但为什么第一个会打印字符串值?在两个示例中删除
&
运算符将解决警告问题。我不确定您的预期行为是什么,但在移动&
操作符时,它们似乎工作正常。这是因为数组本身就是指向数组第一个元素的指针,所以添加&
不是您想要的
工作示例(与和完全相同):
及
在两个示例中删除和运算符将解决警告问题。我不确定您的预期行为是什么,但在移动&
操作符时,它们似乎工作正常。这是因为数组本身就是指向数组第一个元素的指针,所以添加&
不是您想要的
工作示例(与和完全相同):
及
为什么第一个打印字符串值,而第二个给出segfault
案例一发生了什么:
staticArray
的类型是char[100]
,即100
char
&staticArray
的类型是char(*)[100]
scanf()
中的%s
格式说明符期望参数作为指向char
数组初始元素的指针,即char*
类型
您正在将char(*)[100]
类型传递给scanf()
,因此编译器将对此语句发出警告
&staticArray
为您提供指向类型为char(*)[100]
的数组的指针,该数组在数值上与数组的基址相同
考虑这个例子:
#include <stdio.h>
int main(void)
{
char staticArray[100];
printf ("staticArray: %p\n", (void*)staticArray);
printf ("&staticArray : %p\n", (void*)&staticArray);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* dynamicArray;
dynamicArray = malloc(sizeof(char)*100);
if (dynamicArray == NULL) {
exit(EXIT_FAILURE);
}
printf ("dynamicArray: %p\n", (void*)dynamicArray);
printf ("&dynamicArray : %p\n", (void*)&dynamicArray);
free(dynamicArray);
return 0;
}
staticArray
和&staticArray
都会生成指向相同地址的指针1),但它们的类型不同。
这就是为什么当您将&staticArray
传递给scanf()
,在编译过程中由于类型不匹配而收到警告,但当调用scanf()
时,它将该指针视为char*
并读取输入并将结果存储到给定位置。以后打印时,它会打印字符串值
案例二发生了什么:
dynamicArray
的类型是char*
&dynamicArray
的类型是char**
因此,您正在将char**
类型传递到scanf()
,当使用%s
格式说明符时,它需要char*
。因此,编译器正在对此语句发出警告。
指针&dynamicArray
与dynamicArray
不同
考虑这个例子:
#include <stdio.h>
int main(void)
{
char staticArray[100];
printf ("staticArray: %p\n", (void*)staticArray);
printf ("&staticArray : %p\n", (void*)&staticArray);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* dynamicArray;
dynamicArray = malloc(sizeof(char)*100);
if (dynamicArray == NULL) {
exit(EXIT_FAILURE);
}
printf ("dynamicArray: %p\n", (void*)dynamicArray);
printf ("&dynamicArray : %p\n", (void*)&dynamicArray);
free(dynamicArray);
return 0;
}
dynamicArray
和&dynamicArray
都生成不同的指针
当您将&dynamicArray
传递到scanf()
(读取输入并将结果存储到给定位置)时,会导致未定义的行为2,因为您的程序最终访问无效内存
当使用格式说明符%s
,printf()
将&dynamicArray
传递到printf()
时,它会访问该地址以写入字符串,并最终访问无效内存,导致未定义的行为2)。因此,你犯了错误
1) 数组会自动转换为指向其第一个元素的指针,但该规则很少有例外(C11标准#6.3.2.1p3):
- 数组是
sizeof
运算符的操作数
- 数组是
\u Alignof
运算符的操作数
- 数组是
和的操作数
- 数组是用于初始化数组的字符串文字
2) includes可能执行不正确(崩溃或静默生成不正确的结果),也可能意外地完全按照程序员的意图执行
为什么第一个打印字符串值,而第二个给出segfault
案例一发生了什么:
staticArray
的类型是char[100]
,即100
char
&staticArray
的类型是char(*)[100]
scanf()
中的%s
格式说明符期望参数作为指向char
数组初始元素的指针,即char*
类型
您正在将char(*)[100]
类型传递给scanf()
,因此编译器将对此语句发出警告
&staticArray
为您提供指向类型为char(*)[100]
的数组的指针,该数组在数值上与数组的基址相同
考虑这个例子:
#include <stdio.h>
int main(void)
{
char staticArray[100];
printf ("staticArray: %p\n", (void*)staticArray);
printf ("&staticArray : %p\n", (void*)&staticArray);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char* dynamicArray;
dynamicArray = malloc(sizeof(char)*100);
if (dynamicArray == NULL) {
exit(EXIT_FAILURE);
}
printf ("dynamicArray: %p\n", (void*)dynamicArray);
printf ("&dynamicArray : %p\n", (void*)&dynamicArray);
free(dynamicArray);
return 0;
}
staticArray
和&staticArray
都会生成指向相同地址的指针1),但它们的类型不同。
这就是为什么当您将&staticArray
传递给scanf()
,在编译过程中由于类型不匹配而收到警告,但当调用scanf()
时,它将该指针视为char*
并读取输入并将结果存储到给定位置。以后打印时,它会打印字符串值
案例二发生了什么:
dynamicArray
的类型是char*
&dynamicArray
的类型是char**
因此,您正在将char**
类型传递到scanf()
,当%s
格式说明符i