C: много вопросов о char * - PullRequest
       1

C: много вопросов о char *

0 голосов
/ 02 марта 2019

У меня есть куча вопросов о программе на C (arrays-pointers.c), которая имеет проблемы:

#include <stdio.h>

int main(void) {
    char * vowels = {'A', 'E', 'I', 'O', 'U'};

    printf("sizeof(vowels): %d\n", sizeof(vowels));
}

Я компилирую с помощью gcc (gcc arrays-pointers.c -o arrays-pointers.exe), и я получаю предупреждения (но не прямые ошибки):

In function 'main':
warning: initialization of 'char *' from 'int' makes pointer from integer 
    without a cast [-Wint-conversion]
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                   ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                        ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                             ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                                  ^~~
note: (near initialization for 'vowels')
warning: excess elements in scalar initializer
  char * vowels = {'A', 'E', 'I', 'O', 'U'};
                                       ^~~
note: (near initialization for 'vowels')

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

sizeof(vowels): 8

Мои вопросы:

  • Если указатели и массивыпохоже, почему я не могу инициализировать свой массив таким образом?
  • Что означают предупреждения?
  • Почему sizeof(vowels) всегда 8?

Ответы [ 4 ]

0 голосов
/ 02 марта 2019

Прежде всего, как уже было сказано, sizeof (int) = 4 байта в 32-битной архитектуре или 8 в 64-битной архитектуре, это связано с объемом памяти, который требуется вашей системе для кодирования целого числа.Тем не менее, вы должны понимать сходство указателей и массивов в C. Массив - это набор элементов одного типа, сохраняемых в непрерывных адресах в памяти.Мы имеем к нему доступ, используя указатель на первый байт.Так, например:

int A [5];это не указатель, а просто массив, & A или & A [0] (это обозначение имеет то же значение в C), это указатель на начало (вы можете назвать его head, если хотите) массива.

[1] означает, что вторым элементом массива и его адрес (или указатель на него) является & (A + sizeof (int)) == & (A + 4) в 32-битной машине или программном обеспечении, которое имитирует его (NetBeansнапример).

Передача массива функции:

Первый способ:

void readTheTheory (int * Arr) {

}

и назовите его как readTheTheory (A) или readTheTheory (& A [0])

второй путь

void readTheTh (int A [])

{

} и узнайте, как правильно вызвать его самостоятельно

0 голосов
/ 02 марта 2019

Это нетривиально понять, потому что массивы "странные" в C;это своего рода «особый случай» только по историческим причинам.

Что вам нужно знать, так это то, что массивы и указатели - это НЕ одно и то же;массив - это блок памяти с несколькими элементами один за другим, указатель - это адрес чего-то другого.

Что создает некоторую путаницу, так это то, что во многих местах, если вы используете массив, который язык C рассматривает вместомассив указатель на первый элемент массива (по-английски используемая фраза «массив распадается на указатель на первый элемент»).

Например,

int x[] = {1, 2, 3}; // x is an array
foo(x); // you cannot pass an array, a pointer to x[0] is passed instead

, поэтому вашкод недопустим, потому что это похоже на

int *x = {1, 2, 3};  // Invalid: {1, 2, 3} is not a valid initializer for a pointer

, когда вместо этого, как ни странно, это допустимо

int x[] = {1, 2, 3};   // An array
int *y = x;            // Fine, it's like writing int *y = &x[0];

Во втором примере инициализация y действительна, потому что в этом контекстеесть правило, согласно которому массив автоматически «распадается» на указатель на первый элемент.

Эта путаница возникает из-за того, что массивы не являются объектами, подобными другим (по историческим причинам), и, например, присваивают массивы или возвращаютмассив из функции или принятие параметра массива недопустимо (но, что удивительно, вы можете назначить структурупередайте структуры как параметры и верните структуры из функций ... даже если структура содержит массив).Исправление этой нелогичной асимметрии теперь не подлежит сомнению, так как это нарушит большинство существующих программ на C или C ++, изменив смысл существующего кода.

C и C ++, к сожалению, полны этих странных нелогичных правил, поэтому изучение Cили C ++ экспериментальным путем - плохая идея (с C это плохая идея, но может быть выполнимой, поскольку ее размер невелик, но с C ++ это самоубийство, потому что это буквально минное поле нелогичных ловушек и огромное).

Чтобы выучить C или C ++, вам нужно прочитать правила.

Не пытайтесь быть слишком умным и угадывать (угадывание не помогает, когда правильный ответ нелогичен).

0 голосов
/ 02 марта 2019

Вы можете инициализировать его, создав массив символов и назначив указателю его адрес.Этот вид объектов называется составными литералами.

char * vowels = (char []){'A', 'E', 'I', 'O', 'U'};

0 голосов
/ 02 марта 2019

Если указатели и массивы похожи, почему я не могу инициализировать свой массив таким образом?

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

Почему sizeof (гласные) всегда 8?

Это размеруказатель на 64-битную систему.

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