Неверное объявление двумерного массива переменного размера? - PullRequest
0 голосов
/ 29 октября 2019

Вот main.c:

#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
    int size = atoi(argv[1]);

    int int_array[10][10];

    int *before = NULL;
    int *val[size];
    int *after = NULL;
    printf("before:%p, after:%p, sizeof val:%lu\n", before, after, sizeof val);

    int i = 0;
    /*for (; i < 10; i++) {
        val[i] = int_array[i];
    }*/
    val[0] = int_array[0];
    val[1] = int_array[3];

    printf("int_array:%p, int_array[0]:%p, int_array[1]:%p, int_array[2]:%p, int_array[3]:%p\n", int_array, int_array[0], int_array[1], int_array[2], int_array[3]);
    printf("val:%p, val[0]:%p, val[1]:%p, val[2]:%p, val[3]:%p\n", val, val[0], val[1], val[2], val[3]);
    printf("before:%p, after:%p\n", before, after);

    return 0;
}
[root@localhost test]# ./test 3
before:(nil), after:(nil), sizeof val:24
int_array:0x7ffeadc69470, int_array[0]:0x7ffeadc69470, int_array[1]:0x7ffeadc69498, int_array[2]:0x7ffeadc694c0, int_array[3]:0x7ffeadc694e8
val:0x7ffeadc69440, val[0]:0x7ffeadc69470, val[1]:0x7ffeadc694e8, val[2]:0x3, val[3]:0x4005ba
before:(nil), after:(nil)

[root@localhost test]# ./test 6
before:(nil), after:(nil), sizeof val:48
int_array:0x7ffcd30f1f50, int_array[0]:0x7ffcd30f1f50, int_array[1]:0x7ffcd30f1f78, int_array[2]:0x7ffcd30f1fa0, int_array[3]:0x7ffcd30f1fc8
val:0x7ffcd30f1f00, val[0]:0x7ffcd30f1f50, val[1]:0x7ffcd30f1fc8, val[2]:0x7ffcd30f2220, val[3]:(nil)
before:(nil), after:(nil)

скомпилируйте код: gcc -o test main.c, затем я получил вывод выше ./test 3 и ./test 6. так, это не время компиляции, а время выполнения, когда определяется sizeof()?

Ответы [ 3 ]

8 голосов
/ 29 октября 2019

Неправильно ли объявлено 2D-массив переменного размера?

В C ++ размер всех переменных массива должен быть постоянной времени компиляции. size не является константой времени компиляции, поэтому int *val[size]; некорректно сформирован в C ++.

0 голосов
/ 31 октября 2019

Спасибо Джону и Блейзу, и да, это VALs (переменная длина массива), которая поддерживается компилятором GNU C (gcc) как расширение начиная с C99. Так что многое зависит от компилятора.

Здесь можно узнать больше из Википедии:
Распределение

  • Компилятор GNU C выделяет память для VLA с автоматической продолжительностью хранения в стеке. [4]VLA, как и все объекты в C, ограничены байтами SIZE_MAX. [5]
  • VLA также могут быть выделены в куче и доступны с помощью указателя на VLA.
0 голосов
/ 29 октября 2019

Для VLA, да, результат sizeof вычисляется во время выполнения:

6.5.3.4 Операторы sizeof и _Alignof
...
2 Оператор <strong>sizeof</strong> возвращает размер (в байтах) своего операнда, который может быть выражением или именем типа в скобках. Размер определяется по типу операнда. Результатом является целое число. Если тип операнда является типом массива переменной длины, то операнд вычисляется, в противном случае, операнд не оценивается, и результатом является целочисленная константа.

C 2011 Онлайн-черновик

Выделение добавлено.

Это имеет смысл, поскольку размер VLA не устанавливается до времени выполнения.

Я не знаю, чего вы пытаетесь достичь с помощью before и after - если вы пытаетесь увидеть, какие адреса занимает val, это не способ сделатьЭто. Прежде всего, вы захотите напечатать значения &before и &after, но даже при этом нет гарантии, что объекты размещаются в памяти в том же порядке, в котором они были объявлены. Также не гарантируется, что VLA выделяются из той же области памяти, что и другие переменные auto (они обычно есть, но это не обязательно).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...