В соответствии с C99 standard 6.5.2.5 0,9 кода:Новый объект, созданный каждый раз, когда объединенный литерал присваивается указателю в цикле?
int *p = (int []){2, 4};
инициализирует р, чтобы указать на первом элемент массива из двух целых чисел, ФИ сначала, имеющее значение два, а вторые, четыре. Выражения в этот составной литерал должны быть постоянными. Неименованный объект имеет статическую продолжительность хранения.
Но что происходит, когда мы делаем что-то вроде этого:
int* arr[100];
for (int a=0; a<100; a++) {
arr[a] = (int []){2, 4};
}
новый unnamed object
создать с каждой итерации цикла или тот же роект используется для каждой итерации?
ли результат быть иначе, если бы мы сделали что-то вроде этого:
int* ptr = NULL;
for (int a=0; a<100; a++) {
ptr = (int []){2, 4};
}
два возможных варианта: новый объект создается каждый раз, когда итерация цикла или тот же объект, который используется для каждой итерации цикла.
Меня интересует, может ли поведение в этой ситуации каким-то образом быть вычтено из того, что написано в стандарте, или это зависит от компилятора.
Я тестировал его под GCC 4.1.2 с этим кодом:
int main(void) {
int* arr[100];
for (int a=0; a<10; a++) {
arr[a] = (int []){2, 4};
printf("%p ", arr[a]);
}
printf("\n");
}
И результат:
0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0
Я написал код для c щеколда ответ CAF в:
void fillArr(int* arr[]) {
for (int a=0; a<4; a++) {
arr[a] = (int []){a, a};
printf("%p %d | ", arr[a], arr[a][0]);
}
}
void fillArr2(int* arr[]) {
for (int a=0; a<4; a++) {
int temp[] = { a, a };
arr[a] = temp;
printf("%p %d | ", arr[a], arr[a][0]);
}
}
int main(void) {
int* arr[4];
printf("\nfillarr1 function scope\n");
fillArr(arr);
printf("\nfillArr main scope\n");
for (int a=0; a<4; a++) {
printf("%p %d | ", arr[a], arr[a][0]);
}
printf("\nfillArr2 function scope\n");
fillArr2(arr);
printf("\nfillArr2 main scope\n");
for (int a=0; a<4; a++) {
printf("%p %d | ", arr[a], arr[a][0]);
}
printf("\n");
}
И результат (называется его Valgrind для обнаружения ошибок памяти):
==19110== Memcheck, a memory error detector
==19110== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==19110== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==19110== Command: ./a.out
==19110==
fillarr1 function scope
0x7ff000830 0 | 0x7ff000830 1 | 0x7ff000830 2 | 0x7ff000830 3 |
fillArr main scope
==19110== Use of uninitialised value of size 8
==19110== at 0x3E33A41B1D: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A41B27: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A44FBE: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A4574A: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A43C49: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 |
fillArr2 function scope
0x7ff000830 0 | 0x7ff000830 1 | 0x7ff000830 2 | 0x7ff000830 3 |
fillArr2 main scope
==19110== Use of uninitialised value of size 8
==19110== at 0x3E33A41B1D: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A41B27: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A44FBE: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A4574A: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A43C49: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 |
==19110==
==19110== HEAP SUMMARY:
==19110== in use at exit: 0 bytes in 0 blocks
==19110== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==19110==
Так литералы доступны только внутри функции они были объявлены в, выходят из scope после выхода из функции, и после этого доступ к ним является неопределенным поведением.
Ну, вы попробовали? –
Но поскольку объект «имеет статическую продолжительность хранения», я бы сказал, что он всегда будет таким же. –
Да, я сделал, под gcc 4.1.2; но я хотел бы знать общий ответ. Я отредактирую вопрос, thx. – Dariusz