2009-03-03 7 views
3

Этот пример работает отлично:Инициализация массива указателей на указатели

static char *daytab[] = { 
    "hello", 
    "world" 
}; 

Это не:

static char *daytab[] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

Как я вижу в том, что первый пример создает массив, который заполняется с указателями на две строковые литералы (которые сами являются массивами). Второй пример, IMO, должен быть идентичным - создать массив и заполнить его указателями на два массива char.

Может ли кто-нибудь объяснить мне, почему второй пример неверен?

P.S. Вы, вероятно, могли бы написать это так (не проверял):

static char a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
static char b[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
static char *daytab[] = { 
    a, 
    b 
}; 

Но это похоже на слишком много работы :).

+0

4 ответа, но я вижу только один? Как так? – Ree

+0

Удалено автором. –

+0

У меня это случилось на днях. Кажется, что у вас есть время, чтобы полностью учитывать удаленные ответы. Он будет рассчитывать на правильный счет «скоро». – RBerteig

ответ

3

В этом:

{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 

Есть только инициализатор массива. Он сам не создает массив. В первом примере, когда вы назначили строковый литерал указателю, DID создайте эти строки в статическом хранилище (скрытые для вас), а затем просто назначьте указатели на них.

В принципе, нет возможности инициализировать ваш char * с помощью инициализатора массива. Вам нужно создать фактический массив и присвоить ему эти числа. Вам нужно будет сделать что-то вроде:

char a[][] = { {32, 30, 0}, {34, 32, 33, 0} }; // illegal 

Но это незаконно.

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

+0

Nope. Если вы укажете второе измерение, первое может быть оставлено [], поэтому ваш пример/char a [] [12] = {"hello", "world"};/является законным. –

+0

Первый пример совершенно законный - мне не нужно создавать явные указатели на строки. Однако проблема - это ВТОРОЙ пример. – Ree

+0

Почему я могу оставить их пустыми в первом примере, но не вторым? Строковые литералы - это массивы, и во втором примере у меня есть массивы? – Ree

3

Try:

static char daytab[][13] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

Это не символ * 's. Они также не являются символами. Вы, вероятно, хотите:

static int daytab[][13] ... 
+0

Ну, это сделает каждый элемент основного массива размером 13. Что делать, если я хочу иметь указатели на массивы разных размеров? Что касается char - char, можно использовать для небольших целых значений, поэтому здесь проблема не проблема. – Ree

+0

Если вы укажете второе измерение, то сначала определяется список инициализаторов. –

+0

Извините, ваш ответ не связан с моим первоначальным комментарием. Если я сделаю то, что вы говорите, «это сделает каждый элемент основного массива размером 13». Мне нужно инициализировать массив указателей на массивы DIFFERENT. – Ree

0

Синтаксис вашего второго примера - это синтаксис для литерала многомерного массива.

Многомерный массив не является массивом указателей на массивы.

Было бы удивительно, если бы синтаксис для одной вещи был также синтаксисом для другой вещи, в зависимости от типа, который он объявляет.

В первом примере, поскольку строковый литерал оценивается как указатель, а не значение массива, значение оценивается как массив указателей. Поскольку литерал массива оценивается как значение массива, а не указатель, вторым примером является многомерный массив - массив, элементами которого являются значения массива, а не массив, элементы которого являются указателями на значения массива.

Следующий код демонстрирует комбинации многомерных массивов, указатели на массивы, массивы указателей и указатели на указатели.Из этих трех только массивы указателей и указателей на указатели совместимы друг с другом:

void multi_array (int x[][4], size_t len) // multidimensional array 
{ 
    for (size_t i = 0; i < len; ++i) 
     for (size_t j = 0; j < 4; ++j) 
      putchar('a' + x[i][j]); 
    putchar('\n'); 
} 

void ptr_array (int (*x)[4], size_t len) // pointer to an array 
{ ... as multi_array } 

void array_ptr (int *x[], size_t len) // array of pointers 
{ ... as multi_array } 

void ptr_ptr (int **x, size_t len) // pointer to pointer 
{ ... as multi_array } 

int main() { 
    int a[][4] = { { 1,2,3,4 } }; 
    int b[] = { 1,2,3,4 }; 
    int* c[] = { b }; 

    multi_array(a, 1); 
    multi_array((int[][4]) { { 1,2,3,4} }, 1); // literal syntax as value 
    ptr_array(&b, 1); 
    array_ptr(c, 1); 
    ptr_ptr(c, 1); // only last two are the same 

    return 0; 
} 
0

Обратите внимание, что ваш первый пример не работает, либо. Она должна быть:

static const char *daytab[] = { 
    "hello", 
    "world" 
}; 

Обратите внимание на Const.

Редактировать: И «не работает», я имею в виду плохую практику и склонность к ошибкам, что, возможно, еще хуже.

3

Ну, эта нить уже староват, но я имел дело с той же проблемой и нашел способ инициализировать массив указателей на массивы, как это:

#include <iostream> 
using namespace std; 

int *a[] = { 
    (int[]) { 0 } , 
    (int[]) { 1 , 2 } , 
    (int[]) { 3 , 4 , 5 } , 
    (int[]) { 6 , 7 , 8 , 9 } 
}; 

main() 
{ 
    cout 
    << a[0][0] << endl 
    << a[1][0] << " " << a[1][1] << endl 
    << a[2][0] << " " << a[2][1] << " " << a[2][2] << endl 
    << a[3][0] << " " << a[3][1] << " " << a[3][2] << " " << a[3][3] << endl; 
} 

И я получаю выход , компиляции с Gnu г ++

0 
1 2 
3 4 5 
6 7 8 9 

и составитель с интелом ICPC

0 
1 1 
40896 32767 -961756724 
0 32767 4198878 0 

Таким образом, синтаксис с что в принципе это правильно, только что компилятор Intel не поддерживает его, вероятно, из-за отсутствия общего использования этого стиля.


--- редактировать ---

Здесь также версия C (как потребовано):

#include <stdio.h> 

int *a[] = { 
    (int[]) { 0 } , 
    (int[]) { 1 , 2 } , 
    (int[]) { 3 , 4 , 5 } , 
    (int[]) { 6 , 7 , 8 , 9 } 
}; 

int main() 
{ 
    printf("%d\n" , a[0][0]); 
    printf("%d %d\n" , a[1][0] , a[1][1]); 
    printf("%d %d %d\n" , a[2][0] , a[2][1] , a[2][2]); 
    printf("%d %d %d %d\n" , a[3][0] , a[3][1] , a[3][2] , a[3][3]); 
} 

Я тестировал его с GCC и лязгом и печатает правильный результат. КПП. неправильный вывод компилятора Intel был ошибкой компилятора.

+0

ОК, но вопрос строго связан с C (см. Теги), поэтому было бы лучше, если бы ваш пример не содержал код на C++. – Ree

+0

Это тоже не совсем то же самое. Я искал ту же проблему, но мне нужны имена массивов. –

1
static char **daytab; 
daytab=(char**)malloc(2*sizeof(char*)); 
daytab[0]=(char*)(char[]){0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
daytab[1]=(char*)(char[]){0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
Смежные вопросы