C99标准是否允许写复合文字(结构)? 它似乎不提供写文字字符串。 我问这个是因为它在C编程:现代方法,第 406页第2版中说 。
问:允许指向复合文字的指针似乎可以修改文字。 是这样的吗?
答:是的。 复合文字是可以修改的左值。
但是,我不知道它是如何工作的,以及它如何与字符串文字一起工作,你当然无法修改。
char *foo = "foo bar"; struct bar { char *a; int g; }; struct bar *baz = &(struct bar){.a = "foo bar", .g = 5}; int main () { // Segfaults // (baz->a)[0] = 'X'; // printf( "%s", baz->a ); // Segfaults // foo[0] = 'a'; // printf("%s", foo); baz->g = 9; printf("%d", baz->g); return 0; }
您可以在我的列表中看到段错误,写入baz->a
导致段错误。 但是,写信给baz->g
则不然。 为什么其中一个会导致段错而不是另一个? struct-literals与string-literals有何不同? 为什么struct-literals也不会被放入内存的只读部分,并且这两个行为是否定义或未定义(标准问题)?
首先要做的是:你的struct literal有一个初始化为字符串文字的指针成员。 结构本身的成员是可写的,包括指针成员。 只有字符串文字的内容不可写。
字符串文字从一开始就是语言的一部分,而结构文字(官方称为复合文字 )是一个相对较新的添加,从C99开始。 到那时,存在许多实现将字符串文字放在只读存储器中,特别是在具有少量RAM的嵌入式系统上。 到那时,标准的设计者可以选择将字符串文字移动到可写位置,从而允许结构文字是只读的,或者保持原样。 这三种解决方案都不是理想的,所以看起来它们走的是阻力最小的路径,并且一切都按原样保留。
C99标准是否允许写复合文字(结构)?
C99标准没有明确禁止写入使用复合文字初始化的数据对象。 这与字符串文字不同,字符串文字的修改被标准视为未定义的行为。
该标准基本上定义了与字符串文字相同的特征,并使用在函数体外部使用的const
限定类型来复合文字。
一生
可能共享
§6.4.5p7未指定[为字符串文字创建的数组]是否是不同的,前提是它们的元素具有适当的值。
§6.5.2.5p7字符串文字和具有const限定类型的复合文字不需要指定不同的对象。
可变性
§6.4.5p7如果程序试图修改[包含字符串文字的数组],则行为未定义。
§6.7.3p6如果尝试通过使用具有非
const
限定类型的左值来修改使用const
-qualified类型定义的对象,则行为是未定义的。
函数体内复合文字的生命周期是自动的这一事实会导致细微的错误:
/* This is fine */ const char* foo(void) { return "abcde"; } /* This is not OK */ const int* oops(void) { return (const int[]){1, 2, 3, 4, 5}; ;
C99标准是否允许写复合文字(结构)?
通过写复合文字,如果你的意思是修改复合文字的元素,那么是的,如果它不是只读的复合文字,它就会这样做。
C99-6.5.2.5:
如果类型名称指定了未知大小的数组,则大小由6.7.8中指定的初始化程序列表确定, 复合文字的类型是已完成数组类型的类型 。 否则(当类型名称指定对象类型时),复合文字的类型是由类型名称指定的类型。 在任何一种情况下,结果都是左值 。
这意味着,复合文字是像数组一样的左值 ,复合文字的元素可以修改,就像你可以修改聚合类型一样。 例如
// 1 ((int []) {1,2,3})[0] = 100; // OK // 2 (char[]){"Hello World"}[0] = 'Y'; // OK. This is not a string literal! // 3 char* str = (char[]){"Hello World"}; *str = 'Y'; // OK. Writing to a compound literal via pointer. // 4 (const float []){1e0, 1e1, 1e2}[0] = 1e7 // ERROR. Read only compound literal
在您的代码中,您要做的是修改复合文字元素,该元素指向不可修改的字符串文字。 如果使用复合文字初始化该元素,则可以对其进行修改。
struct bar *baz = &(struct bar){.a = (char[]){"foo bar"}, .g = 5};
这个片段现在可以使用了
Segfaults (baz->a)[0] = 'X'; printf( "%s", baz->a );
进一步的标准也给出了一个例子,在上面提到的相同部分中,并区分字符串文字,复合文字和只读复合文字:
13例5以下三个表达方式有不同的含义:
"/tmp/fileXXXXXX" (char []){"/tmp/fileXXXXXX"} (const char []){"/tmp/fileXXXXXX"}
第一个总是具有静态存储持续时间并且具有char的类型数组,但不需要是可修改的; 当它们出现在函数体内时,最后两个具有自动存储持续时间 , 并且这两个中的第一个是可修改的 。
以上就是c/c++开发分享结构vs字符串文字? 只读与读写?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/562778.html