具有数组成员的结构

时间:2018-12-14 04:49:48

标签: c arrays pointers struct

我正在研究结构,并且遇到了一些误解。我写了几个例子:

#include <stdio.h>

struct test{
    char field[16];
};


int main(int argc, char * argv[]){
    const char *string = "some string";
    struct test t1 = {.field = *string};
    struct test t2 = {.field = string};
    struct test t3 = {.field = "some string"};
    struct test t4 = {{'s', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0'}};


    printf("t1::field = %s\n", t1.field); //prints s
    printf("t2::field = %s\n", t2.field); //prints garbage character
    printf("t3::field = %s\n", t3.field); //prints some string
    printf("t4::field = %s\n", t4.field); //prints some string
}

输出:

t1::field = s
t2::field = 4
t3::field = some string
t4::field = some string

ideone

另一个例子是

#include <stdio.h>

struct test{
    char field[16];
};

int main(void) {
    const char *string = {'s', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0'};
    struct test t = {.field = *string};

    printf("t::field = %s\n", t.field); //segfault
}

输出为空。

ideone

这种行为对我来说还不是很清楚。分配数组内存时,我们可以将其第n个元素作为arr[n]扩展为*(arr + n)。因此,我期望我们使用一些char field[16]来初始化char *,将指针所指向的对象视为某个数组的第一个元素就足够了。

但是从行为上判断,我的理解是完全错误的。您能对此做一个简短的解释吗?

3 个答案:

答案 0 :(得分:2)

SELECT REGEXP_REPLACE((REGEXP_REPLACE('<p class="notice">...</p>','[p]','div',1,0,'c')),'(notice)','alert',1,0,'c'); 

包含一个由16个字符组成的字符数组 struct test{ char field[16]; }; 。数组可以初始化或复制到,但不能分配

有效

field

(已初始化 struct test t1 = {.field = *string}; t1.field(例如string[0]或仅*(string + 0)

无效

*string

(尝试为字符串常量分配指针到数组,请参见C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)

有效

    struct test t2 = {.field = string};

(使用字符串文字初始化数组)

有效

    struct test t3 = {.field = "some string"};

({ struct test t4 = {{'s', 'o', 'm', 'e', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0'}}; t4相同,除了使用括号括起来的初始化程序和 named-initializer t3省略,表示从第一个开始填充成员,请参见C11 Standard § 6.7.9 Initialization (p19)

您的“另一个示例” 失败,原因与.field失败相同。

答案 1 :(得分:2)

在第一个程序 The optimistic lock on an entity failed. 中出现错误,因为指针不是char数组的有效初始化器。

在第二个程序struct test t2 = {.field = string};中出现错误,因为指针的初始化程序不能超过1个。

您应该使用显示这些错误的错误消息的编译器,否则您将很难学习C。

答案 2 :(得分:1)

要在David C.的answer上展开:

无论出于何种原因,C都被设计为具有(在很大程度上)用于声明,定义和使用变量的相同语法。这是混淆的永恒根源,尤其是数组。

可以使用数组表示法和指针表示法来访问分配的内存。实际上,数组表示法已被编译器“分解”为指针表示法。

这使人们认为数组实际上是指针-但从源代码角度来看,它们不是指针。

两个主要区别是:

1)两种类型的初始化都根本不同

2)

  • 指针本身就是变量,在“生存”位置具有明显的内存位置,因此可以重新分配或以其他方式操纵。

  • 数组更像是编译器指令。在定义内存期间分配内存时,没有单独的位置存储该内存的地址。取而代之的是,编译器会在机器代码中针对堆栈(基本)指针创建内存偏移,以便对数组进行任何访问。当使用arr_name或&arr_name [0]之类的东西时,会创建一个临时指针(在某些CPU寄存器中),该临时指针可用于访问数组或复制到指针变量中,但它本身并不是一个单独的实体。这就是人们说的“数组衰减”成指针时的意思。

您可能想看看使用指针和数组的反汇编; online tool这个叫做Godbolt的工具非常有用。