В чем разница между char *name[10] и char (*name)[10]?

Я очень смущен тем, что обозначают эти два обозначения. Я знаю, что приоритет () больше, чем [], значит ли это, что char(*name)[10] — указатель, а char *name[10] — массив?

cdecl.org
Inian 15.12.2020 11:43

Да, имя с char (*name)[10] является указателем на массив из 10 символов (name = malloc(1000 * sizeof *name); strcpy(name[123], "foobar");); с именем char *name[10] представляет собой массив из 10 указателей на char (name[4] = malloc(42);).

pmg 15.12.2020 11:44

о, я думал, что char *name[10] является указателем на первый элемент массива «имя», то есть имя [0].

Neeraj-Kumar-Coder 15.12.2020 11:48
sizeof(char (*)[10] ) будет в 10 раз меньше, чем sizeof(char *[10])
12431234123412341234123 15.12.2020 13:20

@NeerajKumar «думал, что char *name[10] является указателем» -> Массивы не являются указателями. Указатели не являются массивами. Это как вы впервые запросили: «char *name[10] - это массив».

chux - Reinstate Monica 15.12.2020 14:07

@chux-ReinstateMonica, пожалуйста, проясните мне одну вещь, сэр, когда я набираю char *a = "Hello", а затем использую printf("%s", a), тогда выводится вся строка «Привет». Значит ли это, что char * эквивалентно string как в C++. Если это не так, то, пожалуйста, помогите мне, как он печатает всю строку «Hello».

Neeraj-Kumar-Coder 15.12.2020 14:15

@NeerajKumar В C++ класс std::string отличается от массива символов. Вы не можете использовать, например, std::string s("Hello"); printf("%s\n", с);; Строковые литералы — это массивы символов.

Vlad from Moscow 15.12.2020 14:17

NeerajKumar, «означает ли это, что char * эквивалентен строке, как в C++» --> не эквивалентен, хотя и имеет некоторое сходство. a это указатель - адрес - это не строка. Это указатель на начало строки. printf("%s", a) получает этот указатель и использует его для чтения и печати содержимого строки: первый символ, затем следующий до '\0'. Очень похоже на адрес дома не в доме, а просто «указатель» на дом. Он не сообщает, где «заканчивается» дом, а только то, где он находится.

chux - Reinstate Monica 15.12.2020 14:32

@chux-ReinstateMonica Я вас понял!, это означает, что char *a является отправной точкой массива неизвестного размера, и когда мы используем printf("%s",a), он будет искать, пока '\0' не будет найден, и напечатает строку. Итак, почему мы инициализируем массив символов, я имею в виду, что мы можем использовать char *arr вместо char arr[10], поскольку выгодно, чтобы размер не был определен, и мы могли хранить столько, сколько захотим.

Neeraj-Kumar-Coder 15.12.2020 14:43

@NeerajKumar char *arr — это адрес «дома» — какого-то дома — где-то, еще не определенного. char arr[10] это дом - его содержимое еще не определено. Да, char *arr может указывать на строку любого размера, но эта строка еще не определена. Мы инициализируем массив символов, чтобы создать строку.

chux - Reinstate Monica 15.12.2020 14:48

@chux-ReinstateMonica хорошо, это означает, что использование char *arr для строки не рекомендуется, мы должны использовать char arr[10]. Спасибо за вашу помощь и потраченное драгоценное время на решение моей проблемы :-)

Neeraj-Kumar-Coder 15.12.2020 14:58

@NeerajKumar С char *arr, arr это не строка. Хотя это может указывать на одно. Передача указателей - хорошая практика. Однако объект должен где-то существовать.

chux - Reinstate Monica 15.12.2020 15:27

@chux-ReinstateMonica хорошо, последнее сомнение, пожалуйста, в char *arr = "Hello", arr быть указателем не принимает адрес, а принимает строку. Как это возможно, когда я использую char *arr = 'Z', он показывает ошибку, и я должен использовать char a = 'Z', а затем char *arr = &a. Означает ли это, что в char *arr = "Hello" двойные кавычки делают две вещи: создают строку с завершающим нулем и, во-вторых, предоставляют адрес первого символа для arr?

Neeraj-Kumar-Coder 15.12.2020 15:33

@NeerajKumar char *arr = "Hello" --> Да. Обратите внимание, что не следует пытаться писать в строковый литерал "Hello". ТТФН.

chux - Reinstate Monica 15.12.2020 15:40

Давайте продолжим обсуждение в чате.

Neeraj-Kumar-Coder 15.12.2020 15:47
Структурированный массив Numpy
Структурированный массив Numpy
Однако в реальных проектах я чаще всего имею дело со списками, состоящими из нескольких типов данных. Как мы можем использовать массивы numpy, чтобы...
T - 1Bits: Генерация последовательного массива
T - 1Bits: Генерация последовательного массива
По мере того, как мы пишем все больше кода, мы привыкаем к определенным способам действий. То тут, то там мы находим код, который заставляет нас...
Что такое деструктуризация массива в JavaScript?
Что такое деструктуризация массива в JavaScript?
Деструктуризация позволяет распаковывать значения из массивов и добавлять их в отдельные переменные.
3
15
1 681
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

int *a[10] — объявляет массив из 10 указателей на целое число.

int (*a)[10] — объявляет указатель на массив из 10 целых чисел.

о, я думал, что char *name[10] является указателем на первый элемент массива «имя», то есть имя [0].

Neeraj-Kumar-Coder 15.12.2020 11:49
Ответ принят как подходящий

Эта декларация

char *name[10];

объявляет массив из 10 элементов типа char *.

Например, такой массив можно инициализировать следующим образом

char *name[10] = { "Peter", "Tom", "Michael" };

Все элементы массива, не имеющие соответствующего инициализатора, будут неявно инициализированы с помощью NULL. То есть приведенное выше объявление эквивалентно

char *name[10] = 
{ 
    "Peter", "Tom", "Michael", NULL, NULL, NULL, NULL, NULL, NULL, NULL 
};

Указатель на первый элемент массива будет выглядеть так

char **p = name;

Указатель на весь массив будет выглядеть так

char * ( *p )[10] = &name;

Эта декларация

char (*name)[10];

объявляет указатель на объект типа массива char[10].

Например, если у вас есть массив, объявленный как

char name_list[][10] =
{
    "Peter", "Tom", "Michael"
};

то вы можете объявить указатель на первый элемент массива, например

char (*name)[10] = name_list;

Указатель на весь массив может быть объявлен как

char ( *p )[3][10] = &name_list;

Вот демонстрационная программа.

#include <stdio.h>

int main(void) 
{
    {
        char *name[10] = { "Peter", "Tom", "Michael" };

        char **p1 = name;
        puts( *p1 );
        
        char * ( *p2 )[10] = &name;
        puts( ( *p2 )[0] ); 
        // or 
        puts( **p2 );
    }
    
    putchar( '\n' );
    
    {
        char name_list[][10] =
        {
            "Peter", "Tom", "Michael"
        };
        
        char ( *p1 )[10] = name_list;
        puts( *p1 );
        
        char ( *p2 )[3][10] = &name_list;
        puts( ( *p2 )[0] ); 
        // or 
        puts( **p2 );
    }

    return 0;
}

Вывод программы

Peter
Peter
Peter

Peter
Peter
Peter

Имейте в виду, что строковые литералы — это const. const char *name[10] = { "Peter", "Tom", "Michael" }; будет правильнее.

12431234123412341234123 15.12.2020 13:01

@ 12431234123412341234123 В C строковые литералы не являются const, даже если код не должен пытаться их изменить.

chux - Reinstate Monica 15.12.2020 14:01

@ 12431234123412341234123 В строковых литералах C есть типы непостоянных массивов символов, хотя вы не можете изменить строковый литерал.

Vlad from Moscow 15.12.2020 14:19

*имя[10]

представляет собой массив из 10 указателей. Обычно они используются при работе с двумерными массивами.

(*имя)[10]

С другой стороны, это в основном указатель на массив из 10 целых чисел или что-то еще.

Другие вопросы по теме