C:关于char *的许多问题

时间:2019-03-02 07:34:11

标签: c arrays pointers

我对有问题的C程序(arrays-pointers.c)有很多疑问:

#include <stdio.h>

int main(void) {
    char * vowels = {'A', 'E', 'I', 'O', 'U'};

    printf("sizeof(vowels): %d\n", sizeof(vowels));
}

我使用gcc(gcc arrays-pointers.c -o arrays-pointers.exe)进行编译,但收到警告(但不是完全错误):

In function 'main':
warning: initialization of 'char *' from 'int' makes pointer from integer 
    without a cast [-Wint-conversion]
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                   ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                        ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                             ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                                  ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                                       ^~~
note: (near initialization for 'vowels')

尽管有这些警告,但gcc会生成一个可执行文件,该可执行文件始终输出:

sizeof(vowels): 8

我的问题是:

  • 如果指针和数组相似,为什么不能以这种方式初始化数组?
  • 警告是什么意思?
  • 为什么sizeof(vowels)总是8?

4 个答案:

答案 0 :(得分:5)

这很容易理解,因为数组在C中是“奇怪的”。仅出于历史原因,它们就是“特殊情况”。

您需要知道的是,数组和指针根本不是一回事。数组是一块具有多个元素的内存块,指针是别的东西的地址。

造成混淆的是,在许多地方,如果使用C语言,而不是使用数组,则C语言会考虑指向数组第一个元素的指针(在法律术语中,用语是“数组衰减为指向数组的指针)。第一个元素”)。

例如

int x[] = {1, 2, 3}; // x is an array
foo(x); // you cannot pass an array, a pointer to x[0] is passed instead

因此您的代码无效是因为

int *x = {1, 2, 3};  // Invalid: {1, 2, 3} is not a valid initializer for a pointer

相反,令人惊讶的是,这是有效的

int x[] = {1, 2, 3};   // An array
int *y = x;            // Fine, it's like writing int *y = &x[0];

在第二个示例中,y的初始化是有效的,因为在这种情况下,有一条规则说该数组会自动“衰减”为指向第一个元素的指针。

之所以会发生这种混乱,是因为数组不是其他对象(出于历史原因),例如,分配数组,从函数返回数组或接受数组参数是非法的(但令人惊讶的是,您可以分配结构,将结构作为参数传递,并从函数返回结构...即使结构包含数组也是如此。现在解决这种不合逻辑的不对称性已成问题,因为通过更改现有代码的含义会破坏大多数现有的C或C ++程序。

不幸的是,

C和C ++充满了这些奇怪的不合逻辑的规则,这就是为什么通过实验学习C或C ++是一个坏主意的原因(对于C语言来说,这是一个坏主意,但由于它的体积很小,可能仍然可行,但是对于C ++语言,自杀,因为这实际上是一个不合逻辑的陷阱的雷区,也是一个巨大的陷阱。)

要学习C或C ++,您需要阅读规则。

不要试图太聪明和猜测(正确答案不合逻辑时,猜测无济于事。

答案 1 :(得分:2)

您可以通过创建字符数组,然后为指针分配其地址来对其进行初始化。这种对象称为复合文字。

{{1}}

答案 2 :(得分:0)

  

如果指针和数组相似,为什么不能初始化数组   这样吗?

从技术上讲,它们并不完全相同。您可以添加手动操作以使指针的行为类似于数组,但它们并不相同。

  

为什么sizeof(元音)总是8?

它是64位系统上指针的大小。

答案 3 :(得分:0)

首先,因为已经说过sizeof(int)=在32位体系结构中为4个字节,在64位体系结构中为8个字节,这与系统对整数进行编码所需的内存量有关。 话虽如此,您必须了解C中的指针和数组的相似性。数组是保存在内存中连续地址中的相同类型元素的集合。我们可以使用指向它的第一个字节的指针来访问它。例如:

int A [5];不仅是数组的指针,&A或&A [0](在C中表示相同的含义)是指向数组的开始(如果需要,可以将其命名为head)的指针。

A [1]表示数组的第二个元素,它的地址(或指向它的指针)在模拟的32位机器或软件中为&(A + sizeof(int))==&(A + 4)它(例如NetBeans)。

将数组传递给函数:

第一种方式

void readTheTheory(int * Arr) {

}

并将其命名为readTheTheory(A)或readTheTheory(&A [0])

第二种方式

避免readTheTh(int A [])

{

} 并找出如何自行正确调用