在C语言中,char数组和char指针有什么区别?

12 浏览
0 Comments

在C语言中,char数组和char指针有什么区别?

我正在努力理解C语言中的指针,但我目前对以下内容感到困惑:\n

    \n

  • char *p = "hello"
    

    \n这是一个指向以h开头的字符数组的字符指针。

  • \n

  • char p[] = "hello"
    

    \n这是一个存储hello的数组。

  • \n

\n当我将这两个变量传递给以下函数时有什么区别?\n

void printSomething(char *p)
{
    printf("p: %s",p);
}

0
0 Comments

在C语言中,char数组和char指针有什么区别?这个问题的出现是因为在C语言中,有两种不同的字符字符串字面值的用法。

第一种用法是用来初始化char数组。这个用法是一种快捷方式,可以将字符字符串字面值直接赋值给char数组。例如:char c[] = "abc"; 这样的赋值实际上相当于 char c[] = {'a', 'b', 'c', '\0'};。和其他普通数组一样,c数组是可以修改的。

第二种用法是在其他地方使用字符字符串字面值。在这种情况下,字符字符串字面值会生成一个没有名字的、具有静态存储的字符数组,并且在修改时会产生未定义行为。例如:char *c = "abc"; 这样的赋值实际上相当于 static char __unnamed[] = "abc"; char *c = __unnamed;。注意,这里有一个从char数组到char指针的隐式转换,这种转换是合法的。然而,如果修改了c[0],也就是修改了__unnamed数组,就会产生未定义行为。

C99标准的草案中对这个问题进行了详细的说明。在6.4.5 "String literals"和6.7.8/14 "Initialization"中都有相关的规定。

在实际的编译器实现中,GCC 4.8 x86-64 ELF将char指针存储在.rodata节中,而不是.text节中。而char数组则存储在栈中。需要注意的是,默认的链接脚本将.rodata节和.text节放在同一个段中,该段具有执行权限但没有写权限。

总结起来,char数组和char指针的区别在于char数组可以修改,而char指针在修改时会产生未定义行为。这个问题的解决方法是根据具体的需求选择使用char数组还是char指针。

0
0 Comments

在C语言中,char数组和char指针是不同的类型,编译器对它们进行不同的处理。char指针是地址加上指针类型的表示,而char数组是指针加上可选的数组长度(如果已知,比如静态分配的数组)。在运行时,它们之间没有区别(在汇编语言中,几乎没有区别)。

在上述代码中,我们可以看到使用sizeof操作符来获取变量的大小。对于char指针p,sizeof(p)返回的是指向char的指针的大小,在x86架构上是4字节,在x86-64上是8字节。对于char数组q,sizeof(q)返回的是内存中char数组的大小,即6个字节。使用strlen函数可以获取字符串的长度,对于p和q都返回5。

关于字符串字面值的初始化方式,C语言标准中有两种略微不同的用法。一种是作为char数组的初始化器,这样可以指定数组中字符的初始值(如果需要,也可以指定数组的大小)。另一种是在其他地方使用,它会变成一个无名的静态字符数组,并且可能存储在只读内存中,因此不能修改。在表达式上下文中,该数组会立即转换为指针,因此第二种声明将指针p初始化为指向无名数组的第一个元素。

有些编译器具有控制字符串字面值是否可写的开关(用于编译旧代码),而有些编译器可能有选项,将字符串字面值正式处理为const char数组(用于更好的错误检测)。

在代码中还提到了sizeof(q)中为什么q不会衰变为指针,原因是sizeof是一个操作符,而不是一个函数(即使sizeof是一个函数,只有当函数期望一个char指针时,q才会衰变为指针)。

以上就是char数组和char指针在C语言中的区别以及相关问题的解释。

0
0 Comments

C语言中的字符数组(char array)和字符指针(char pointer)是不同的类型,但在某些情况下并不明显。这是因为数组会衰变成指针,意味着如果一个char[]类型的表达式被用于需要char*类型的地方,编译器会自动将数组转换为指向其第一个元素的指针。

例如,我们有一个函数printSomething,它需要一个指针作为参数,如果我们尝试像这样将一个数组传递给它:

char s[10] = "hello";

printSomething(s);

编译器会假装你写的是这样的:

char s[10] = "hello";

printSomething(&s[0]);

这是因为在C语言中,数组名实际上是指向数组第一个元素的指针。

不过,从2012年到现在有什么变化吗?字符数组"s"打印整个数组,即"hello"。

不,数据的存储方式和对数据的处理是两个不同的问题。这个例子打印整个字符串,是因为printf函数处理%s格式字符串的方式是从提供的地址开始,直到遇到空字符终止符。如果你只想打印一个字符,你可以使用%c格式字符串。

我想问一下char *p = "abc",NULL字符\0会自动添加在末尾,就像char[]数组一样吗?

为什么我可以设置char *name; name="123";,但是不能使用int类型做同样的操作?而且在使用%c打印name后,输出是无法读取的字符串:�?

答案是,当你写char *p = "abc";时,编译器会在字符串末尾自动添加一个NULL字符\0。这是因为字符串字面量在C语言中被视为字符数组,并且会自动在末尾添加一个NULL字符。

至于为什么你可以设置char *name; name="123";,但是不能使用int类型做同样的操作,这是因为在C语言中,字符串字面量是常量,而int类型的变量不是常量。

关于使用%c打印name输出无法读取的字符串的问题,这是因为%c格式字符串用于打印一个字符,而name是一个指向字符串的指针。要正确地打印字符串,你应该使用%s格式字符串。

总结起来,char数组和char指针在C语言中是不同的类型。数组名会自动衰变为指向数组第一个元素的指针。字符串字面量会自动在末尾添加一个NULL字符。在使用printf函数打印字符串时,应该使用%s格式字符串。

0