c - 字符串和结构的奇怪行为

标签 c string struct printf

我一直在使用下面的代码时遇到问题,我想了解为什么它不起作用。当我直接在结构中使用从函数返回的字符串时,我的行为很奇怪。

第一个 printf 没有问题,与第二个和第三个相同,但由于某种原因,最后一个出现段错误或只是打印一个随机字符串。如果我尝试在结构中使用 char 指针而不是数组,问题就不会出现。

#include <stdio.h>

typedef struct
{
    int value;
    char string[23];
} Test;

Test func()
{
    Test nuovo = {5, "test"};
    return nuovo;
}

int main()
{
    Test test = func();
    printf("\n1: %d", func().value);

    printf("\n2: %s", test.string);

    printf("\n3: %s", &(func().string[0]));

    printf("\n0: %s", func().string);
    return 0;
}

输出:

====================[ Build | test | Debug ]====================================
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" --build C:\Users\rober\CLionProjects\test\cmake-build-debug --target test -- -j 4
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -SC:\Users\rober\CLionProjects\test -BC:\Users\rober\CLionProjects\test\cmake-build-debug --check-build-system CMakeFiles\Makefile.cmake 0
C:/MinGW/bin/mingw32-make.exe -f CMakeFiles\Makefile2 test
mingw32-make.exe[1]: Entering directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -SC:\Users\rober\CLionProjects\test -BC:\Users\rober\CLionProjects\test\cmake-build-debug --check-build-system CMakeFiles\Makefile.cmake 0
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -E cmake_progress_start C:\Users\rober\CLionProjects\test\cmake-build-debug\CMakeFiles 2
C:/MinGW/bin/mingw32-make.exe -f CMakeFiles\Makefile2 CMakeFiles/test.dir/all
mingw32-make.exe[2]: Entering directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
C:/MinGW/bin/mingw32-make.exe -f CMakeFiles\test.dir\build.make CMakeFiles/test.dir/depend
mingw32-make.exe[3]: Entering directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -E cmake_depends "MinGW Makefiles" C:\Users\rober\CLionProjects\test C:\Users\rober\CLionProjects\test C:\Users\rober\CLionProjects\test\cmake-build-debug C:\Users\rober\CLionProjects\test\cmake-build-debug C:\Users\rober\CLionProjects\test\cmake-build-debug\CMakeFiles\test.dir\DependInfo.cmake --color=
Scanning dependencies of target test
mingw32-make.exe[3]: Leaving directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
C:/MinGW/bin/mingw32-make.exe -f CMakeFiles\test.dir\build.make CMakeFiles/test.dir/build
mingw32-make.exe[3]: Entering directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
[ 50%] Building C object CMakeFiles/test.dir/main.c.obj
C:\MinGW\bin\gcc.exe   -Wall -Wextra -Wpedantic -g   -std=gnu90 -o CMakeFiles\test.dir\main.c.obj   -c C:\Users\rober\CLionProjects\test\main.c

C:\Users\rober\CLionProjects\test\main.c: In function 'main':
C:\Users\rober\CLionProjects\test\main.c:17:19: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char[23]' [-Wformat=]
     printf("\n0: %s", func().string);
                   ^
[100%] Linking C executable test.exe
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -E cmake_link_script CMakeFiles\test.dir\link.txt --verbose=1
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -E remove -f CMakeFiles\test.dir/objects.a
C:\MinGW\bin\ar.exe cr CMakeFiles\test.dir/objects.a @CMakeFiles\test.dir\objects1.rsp
C:\MinGW\bin\gcc.exe -Wall -Wextra -Wpedantic -g   -Wl,--whole-archive CMakeFiles\test.dir/objects.a -Wl,--no-whole-archive  -o test.exe -Wl,--out-implib,libtest.dll.a -Wl,--major-image-version,0,--minor-image-version,0 @CMakeFiles\test.dir\linklibs.rsp
mingw32-make.exe[3]: Leaving directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
[100%] Built target test
mingw32-make.exe[2]: Leaving directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'
"C:\Program Files\JetBrains\CLion 2018.2.6\bin\cmake\win\bin\cmake.exe" -E cmake_progress_start C:\Users\rober\CLionProjects\test\cmake-build-debug\CMakeFiles 0
mingw32-make.exe[1]: Leaving directory 'C:/Users/rober/CLionProjects/test/cmake-build-debug'

Build finished

最佳答案

在 C90 下 func().string 不是左值,非左值数组不会衰减为指针。

编译器只是告诉你:

C:\Users\rober\CLionProjects\test\main.c:17:19: warning: format '%s'
expects argument of type 'char *', but argument 2 has type 'char[23]' 
[-Wformat=]
     printf("\n0: %s", func().string);

这使得 func().string 的使用几乎都是非法的。不要那样做。

我没有很好的 C90 标准版本,但据我所知,它应该在某个地方说类似的内容:

3.2.2.1 Lvalues and function designators

[...] an lvalue that has type "array of type T" is converted to an expression that has type "pointer to type T" that points to the initial member of the array object [...]

关于c - 字符串和结构的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53696339/

相关文章:

c++ - 将结构添加到映射 C++

c++ - struct stat c++ 不在不同的计算机上编译

c - 为什么 *pp[0] 等于 **pp

c - 如何测试 Linux 内核源代码中的特定 .c 文件是否构建?

c++ - 如何使用 MPI 收集行和列分区矩阵?

perl - 如何在perl中一次使用严格的地方处理多行字符串?

string - 从三角不等式理解 BK 树 : How do we derive the (d-n, d+n) 范围?

c - 我的特殊字符计数器出了什么问题?

string - Base64 字符串中的文件比原始文件占用更多空间

c - 错误: Expected identifier or '(' before 'int'