Странное поведение со строками и структурами - PullRequest
0 голосов
/ 09 декабря 2018

У меня были проблемы с кодом ниже, и я хотел бы понять, почему он не работает.Я получаю странное поведение, когда я напрямую использую строку внутри структуры, возвращенную из функции.

Первый printf работает без проблем, так же, как второй и третий, но по какой-то причине последний выходит из-за ошибки сегментации или просто печатает случайную строку.Проблема не проявляется, если я пытаюсь использовать указатель на символ в структуре вместо массива.

#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 голосов
/ 10 декабря 2018

Под C90 func().string не является lvalue, и массив без lvalue не распадается на указатель.

Компилятор говорит вам только что:

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 L-значения и указатели функций

[...] и lvalue с типом «массив типа T» преобразуется в выражение с типом «указатель на тип T», указывающеек начальному члену объекта массива [...]

...