字符串和结构的怪异行为

时间:2018-12-09 20:23:22

标签: 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

1 个答案:

答案 0 :(得分:5)

在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左值和函数指示符

     

[...]类型为“ T型数组”的左值被转换为类型为“ T型指针”的表达式,该表达式指向数组对象的初始成员[...]