结构中的字符数组 - 不兼容的分配? [复制]

Posted

技术标签:

【中文标题】结构中的字符数组 - 不兼容的分配? [复制]【英文标题】:Char array in a struct - incompatible assignment? [duplicate] 【发布时间】:2010-11-20 12:36:36 【问题描述】:

我试图找出一个结构到底是什么并遇到了一个问题,所以我真的有两个问题:

1) 'sara' 中保存了什么?它是指向结构的第一个元素的指针吗?

2) 更有趣的问题:为什么不编译? GCC 说“test.c:10: error: incompatible types in assignment”,我不知道为什么...... (这部分已经被你的回答解决了,太好了!)

#include <stdio.h>

struct name 
    char first[20];
    char last[20];
;

int main() 
    struct name sara;
    sara.first = "Sara";
    sara.last = "Black";
    printf("struct direct: %x\n",sara);

    printf("struct deref: %x\t%s\n", *sara, *sara);



感谢您的帮助!

【问题讨论】:

哇。但我确实搜索过:D 【参考方案1】:

这与结构无关 - C 中的数组不可赋值:

char a[20];
a = "foo";   // error

你需要使用strcpy:

strcpy( a, "foo" );

或在您的代码中:

strcpy( sara.first, "Sara" );

【讨论】:

+1 对于strcpy 超过strncpy... :) 我会先使用 char*; sara.first = "Sara",因为我只在真正需要时才使用固定大小的数组;这是一个好习惯还是坏习惯(在 C 中,而不是 C++ 中)? @gramm 如果你这样做,你就是在致力于动态内存管理,这可能不是必需的或不可取的。 @gramm 在很多情况下,数组表现得更好。使用char *sara.first="Sara"; sara.first[0]='s'; 会死得很惨,因为字符串"Sara" 在只读内存中。 @GManNickG 你能否详细说明为什么strncpy 不好?【参考方案2】:

或者你可以只使用动态分配,例如:

struct name 
  char *first;
  char *last;
;

struct name sara;
sara.first = "Sara";
sara.last = "Black";
printf("first: %s, last: %s\n", sara.first, sara.last);

【讨论】:

这不是动态分配。字符串“Sara”和“Black”是在编译时创建的,您只需在运行时将结构成员指向这些字符串。【参考方案3】:

你也可以这样初始化:

struct name sara =  "Sara", "Black" ;

因为(作为一种特殊情况)您可以从字符串常量初始化字符数组。

现在,至于结构实际上是什么 - 它是由其他值组成的复合类型。 sara 在内存中实际上看起来是一个 20 个连续 char 值的块(可以使用 sara.first 引用,后跟 0 个或多个填充字节,然后是另一个 20 个连续 char 值的块(可以引用使用sara.last)。struct name 类型的所有其他实例都以相同的方式布局。

在这种情况下,几乎不可能有任何填充,因此struct name 只是一个由 40 个字符组成的块,您可以为其命名为前 20 个和后 20 个字符。

您可以使用sizeof(struct name) 找出struct name 占用的内存块有多大,并且您可以使用offsetof(struct name, first)offsetof(struct name, last) 找出该结构的每个成员在该内存块中的位置.

【讨论】:

【参考方案4】:

使用strncpy 确保没有缓冲区溢出。

char name[]= "whatever_you_want";
strncpy( sara.first, name, sizeof(sara.first)-1 );
sara.first[sizeof(sara.first)-1] = 0;

【讨论】:

这假设静默截断数据不会导致您的程序在其他地方失败。显式处理字符串不适合缓冲区的情况通常比使用 strcpy 调用未定义行为或使用 strncpy 将程序置于意外状态更好。但我概括一下 - 如果您的程序的其余部分考虑了静默截断(例如,从不期望 sara.first 将匹配“whatever_you_want”),那么程序状态并不意外。 @onebyone 这种行为必须记录在合同中。 如果这已经足够了,那么为什么不直接记录输入字符串不能超过结构可以处理的长度呢?问题是设计帮助客户避免错误的 API 之一。 IMO,默默地忽略可能是错误的东西并没有这样做。但正如我所说,我是在概括,这可能不是一个错误。如果该函数被称为“StoreFirst20CharsOf”,那么我们可以合理地假设任何查看调用代码的人都会理解它的作用。所以 strncpy 有一些用途。 StoreFirst20CharsOf 绝对是这样做的方式...... @SteveJessop:简单地记录输入字符串不能超过特定长度会导致缓冲区溢出。恕我直言,最好记录 API 将截断超过 20 个字符的名称,并且不要引入缓冲区溢出漏洞。并且截断不必是无声的;如果调用者关心,API 可以向调用者发出截断发生的信号。虽然截断可能有时会导致错误,但缓冲区溢出总是是错误(并且是最糟糕的错误之一)。【参考方案5】:

sara 是结构本身,而不是指针(即表示存储实际结构数据的堆栈位置的变量)。因此,*sara 没有意义,不会编译。

【讨论】:

【参考方案6】:

您可以使用 strcpy 来填充它。你也可以从另一个结构初始化它。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct name 
    char first[20];
    char last[20];
;

int main() 
    struct name sara;
    struct name other;

    strcpy(sara.first,"Sara");
    strcpy(sara.last, "Black");

    other = sara;

    printf("struct: %s\t%s\n", sara.first, sara.last);
    printf("other struct: %s\t%s\n", other.first, other.last);


【讨论】:

【参考方案7】:

Sara 结构是一个包含变量的内存块。经典声明几乎没有区别:

char first[20];
int age;

还有一个结构:

struct Person
char first[20];
int age;
;

在这两种情况下,您只是分配一些内存来存储变量,并且在这两种情况下都会保留 20+4 个字节。在您的情况下,Sara 只是一个 2x20 字节的内存块。

唯一的区别是,对于一个结构,内存是作为一个单独的块分配的,所以如果你取 Sara 的起始地址并跳转 20 个字节,你会找到“last”变量。这有时很有用。

查看http://publications.gbdirect.co.uk/c_book/chapter6/structures.html 了解更多信息:)。

【讨论】:

Sara 是一个至少 2 * 20 字节的内存块。如果有填充,它可能会更多。 而且offsetof(struct name, last) 也不一定是 20(尽管几乎可以肯定是)。 不知道。指定可变大小时是否有填充的可能性?例如,无符号字符速度:7;无符号字符标志:3;等等......我在工作中使用它并且从来没有遇到过填充和数据对齐的问题。 如果位域跟在一个非位域成员之后,那么可以有 before 的填充。不允许在 两个相邻位域之间填充,除非它们不适合用于保存它们的相同“基本存储单元”(例如,如果您的实现使用 8 位chars 来保存位域,那么它可能会为flags 开始一个全新的字符,而在保存speed 的字符中留下一个未使用的位)。在底层类型中,位域是从左到右还是从右到左分配也是左定义的。 从技术上讲,第二个还没有分配任何东西。它只是说“如果你稍后看到Person 类型的数据,它的布局是这样的”【参考方案8】:

你可以这样试试。我在我的案例中应用了这个。

#include<stdio.h>

struct name


  char first[20];

  char last[30];

;

//globally

// struct name sara="Sara","Black";

int main()

 

//locally

struct name sara="Sara","Black";


printf("%s",sara.first);

printf("%s",sara.last);


【讨论】:

以上是关于结构中的字符数组 - 不兼容的分配? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

将二维指针数组中的字符串分配给一维指针数组

C中结构内的字符串数组,无需分配

关于C中的结构,如何将数据从结构复制到字符串数组

将二维数组分配为结构成员

指向动态二维字符数组的三重指针的内存分配

将字符串从main复制到结构c