Установка указателя на блок памяти стека?

Я хочу создать указатель на блок памяти стека. Я не хочу копировать содержимое, просто укажите на него указатель. Как мне это сделать?

Это то, что я пробовал...

char p[3][2] = { 1,2,3,4,5,6 };
printf("\nLIST:%d,%d,%d,%d,%d,%d\n", p[0][0], p[1][0], p[2][0], p[0][1], p[1][1], p[2][1]); //works fine 

char pc[3][2] = { 1,2,3,4,5,6 };
char **p = (char**)pc;//No error here... but shows on next line when accessing through the pointer
printf("\nLIST:%d,%d,%d,%d,%d,%d\n", p[0][0], p[1][0], p[2][0], p[0][1], p[1][1], p[2][1]);  //ERROR:  an Exception thrown here... 

person jdl    schedule 04.01.2018    source источник
comment
a снизит его, так как это тип, определяемый пользователем.   -  person jdl    schedule 05.01.2018
comment
повторно открыт - это вопрос C, другое предложение было C++, и вопросы в любом случае были разными (в этом одном OP просто хочет char (*p)[2], тогда как в другом вопросе OP нужен указатель на указатель)   -  person M.M    schedule 05.01.2018
comment
@М.М. Именно так, хотя, учитывая сообщения об ошибках, о которых ОП сообщил о предлагаемых решениях, я подозреваю, что он использует компиляцию С++. Я не согласен, что вопрос не в противном случае то же самое однако. Вопрос явно показывает попытку доступа к pointer[0][1], для которой указатель на указатель не будет работать. Фрагмент кода здесь более или менее идентичен. Однако принятый ответ неверен - правильный ответ, который следует за ним с большим количеством голосов. stackoverflow.com/ вопросы/10165627/   -  person Clifford    schedule 05.01.2018
comment
@Clifford в C ответ является хорошей практикой, а не бесконечно противным, как следует из этого ответа. (На самом деле я бы не назвал это бесконечно неприятным и на С++). И ОП в этой ветке сказал, что этот ответ не решил их проблему.   -  person M.M    schedule 05.01.2018
comment
@М.М. Это не решило проблему, потому что он неправильно понял ответ. Это был указатель на любое количество одномерных массивов, и каждый из них может быть проиндексирован. Чего не хватало в ответе, так это демонстрации доступа к содержимому массива через указатель с использованием двух измерений.   -  person Clifford    schedule 05.01.2018


Ответы (4)


Указатели не являются массивами, и char** не сохраняет информацию, необходимую для индексации второго измерения любого массива, на который он может указывать.

Таким образом, вместо char** вам нужен указатель на массив char[2], потому что в противном случае размер второго измерения pc не известен p, так что p[n] невозможно определить.

Вы можете решить эту проблему, объявив указатель на массив следующим образом:

char pc[3][2] = { 1,2,3,4,5,6 }; 
char (*p)[2] = pc;
printf("\nLIST:%d,%d,%d,%d,%d,%d\n", p[0][0], 
                                     p[1][0], 
                                     p[2][0], 
                                     p[0][1], 
                                     p[1][1], 
                                     p[2][1] ) ;

Для получения правильных результатов размер указателя p должен точно совпадать со вторым измерением двумерного массива pc массива.

person Clifford    schedule 04.01.2018
comment
используя ваш код, я получаю сообщение об ошибке: «инициализация»: невозможно преобразовать из «char **» в «char (*) [2]» - person jdl; 05.01.2018
comment
Этот ответ не имеет смысла - person M.M; 05.01.2018
comment
@ М. М. Каким образом? - person Clifford; 05.01.2018
comment
В любом случае - person M.M; 05.01.2018
comment
@jdl: он выдаст сообщение об ошибке, которое вы описываете, если вы используете компиляцию C ++, но вы пометили вопрос C. - person Clifford; 05.01.2018
comment
comment
Почему вы хотите преобразовать pc в char **? - person klutt; 05.01.2018
comment
@klutt: я не - моя ошибка - скопирована из исходного кода. Теперь он работает на C и C++. Спасибо. - person Clifford; 05.01.2018
comment
Страница, на которую вы ссылаетесь, подавляет сообщения об ошибках, код содержит нарушение ограничения (char ** нельзя неявно преобразовать в char (*)[2]). char ** в коде OP не работало, потому что char ** означает указатель на char*, и в первую очередь не было объекта char *, на который можно было бы указать. Это не имеет ничего общего с информацией о размерах и размерах, как вы предлагаете. - person M.M; 05.01.2018
comment
Вопрос все еще остается ... могу ли я установить указатель на это без каких-либо измерений ... и позже работать с размерами в memcpy? - person jdl; 05.01.2018
comment
char* p = &pc[0][0]; даст вам указатель на блок памяти без информации о размерах. - person Igor Tandetnik; 05.01.2018
comment
@jdl вы никогда не упоминали о рабочих размерах позже в memcpy в своем первоначальном вопросе. Если у вас все еще есть проблема, опубликуйте новый вопрос, который касается вашей реальной проблемы. (Не редактируйте этот вопрос, чтобы задать новый вопрос) - person M.M; 05.01.2018
comment
@jdl: С уважением, этот вопрос не остается; вы не задавали этот вопрос. - person Clifford; 05.01.2018
comment
@Clifford char (*p)[2] = (char **)pc; является ошибкой как в C, так и в C++. (Я могу процитировать соответствующие стандартные абзацы, если хотите). Обновленный код в этом ответе правильный, и обновление второго абзаца хорошее, хотя первый абзац все еще фиктивный. - person M.M; 05.01.2018
comment
Пробраться сюда, прежде чем лечь спать: @M.M прав до сих пор по всем пунктам. - person Bathsheba; 05.01.2018
comment
@М.М. Существует общая точка зрения, что указатели не имеют информации о количестве объектов, на которые они указывают, и это то, что я пытался выразить, возможно, несколько неэлегантно. Я повторил это. Ваша помощь в улучшении ответа приветствуется. Что касается приведения (char**) и OnlineGDB - он выдает ошибку для компиляции C14, но я выбрал C (который, похоже, является ISO C99), вопрос помечен как [visual-c++], чья компиляция C является только ISO C90. Тем не менее, это была ошибка копирования и вставки из исходного кода OP, а не преднамеренная. - person Clifford; 05.01.2018
comment
Как упоминалось ранее, используемый вами сайт подавляет сообщения об ошибках. Редактирование вашего первого параграфа не помогает - оно описывает, почему char * не будет работать для этой цели; причина, по которой char ** не работает, по-прежнему заключается в том, что нет объектов char *, на которые можно было бы указать. - person M.M; 05.01.2018
comment
@М.М. Он использует GCC 5.4.1 C99. К сожалению, он не отображает настройки компилятора и не позволяет точно управлять ими. Я предполагаю, что это значения по умолчанию, например, нет --pedantic -Werror, это, по-видимому, настолько разрешительно, насколько позволяет C99. - person Clifford; 05.01.2018
comment
@M.M: я изменил его дальше. Вы можете редактировать его. Время, которое вы потратили на это, однако вы могли бы сами опубликовать ответ. - person Clifford; 05.01.2018

Вы должны различать указатели и массивы.

char **p означало, что p является указателем на указатель на char. Вместо этого используйте char *p.

char *p = &pc;

Это не дает вам возможности использовать нотацию p[x][y]. Для этого мы можем сделать так:

char (*p)[2] = pc;

Это работает, когда я попробовал ваш код. Вот это полное основное:

int main()
{
    char pc[3][2] = { 1,2,3,4,5,6 };
    char (*p)[2] = pc;
    printf("\nLIST:%d,%d,%d,%d,%d,%d\n", p[0][0], p[1][0], p[2][0], p[0][1], p[1][1], p[2][1]);
}

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

$ ./a.out 

LIST:1,3,5,2,4,6

Чтобы убрать предупреждение, измените

char pc[3][2] = { 1,2,3,4,5,6 };

to

char pc[3][2] = { {1,2},{3,4},{5,6} };

Спасибо M.M. за улучшения.

person klutt    schedule 04.01.2018
comment
Если я изменю его на определение char pc[6] = { 1,2,3,4,5,6 }; Я получаю сообщение об ошибке: «инициализация»: невозможно преобразовать «char()[6]» в «char». - person jdl; 05.01.2018
comment
@jdl попробуй сейчас - person klutt; 05.01.2018
comment
Код серьезности Описание Ошибка состояния подавления строки файла проекта C2440 «инициализация»: невозможно преобразовать «char ( * )[3][2]» в «char ( * )[2]» - person jdl; 05.01.2018
comment
@jdl Какой компилятор вы используете? У меня работает без нареканий и без предупреждений с -Wall -Wextra - person klutt; 05.01.2018
comment
компилятор VS2017 - person jdl; 05.01.2018
comment
Парень ниже... работает... однако... вопрос все еще остается... могу ли я установить указатель на это без каких-либо размеров... и позже работать с размерами в memcpy? - person jdl; 05.01.2018
comment
@M.M Спасибо. Слишком много копий вставки вперед и назад. - person klutt; 05.01.2018

Указатель — это переменная, в которой хранится адрес памяти чего-либо. Следовательно, вам нужно присвоить адрес памяти pc указателю на pc. Вы получаете адрес памяти чего-либо с помощью оператора адреса &.

Указатель на компьютер

CHAR *ppc = &pc[0];

или просто:

CHAR *ppc = pc;
person LosWochos    schedule 04.01.2018
comment
при построении из вашего ответа: я получаю сообщение об ошибке: «инициализация»: невозможно преобразовать из «char () [3] [2]» в «char» - person jdl; 05.01.2018
comment
Извиняюсь. Я допустил ошибку. Поскольку pc — это массив, вам нужен немного другой синтаксис. - person LosWochos; 05.01.2018

Вот что я сделал: (я не хочу указывать размер указателя при его определении. При переопределении я укажу размер)

//assigning a pointer to a matrix
char pc[3][2] = { 1,2,3,4,5,6 };
char *pp;//this pointer(as a member) will be carried between classes.      
pp = &pc[0][0];//set pointer to the address of the first element:  via:  Igor Tandetnik

//redefining, validation and display
char p[2][3]; 
memcpy(p, pp, sizeof(char) * 6);
printf("\nLIST:%d,%d,%d,%d,%d,%d\n", p[0][0], p[1][0], p[2][0], p[0][1], p[1][1], p[2][1]);

Что интересно, для массива 1d вы устанавливаете указатель на имя массива (адрес), а не на адрес первого элемента.

char pc[6] = { 1,2,3,4,5,6 };
char *pp;
pp = pc;//set pointer to the address of the 'pc', not the first element  
person jdl    schedule 05.01.2018