2017-01-31 8 views
1

Я хочу выделить некоторую память указателю с помощью функции. Ниже приводится код, который я написал:Невозможно выделить память внутри функции и вернуть ее в C

#include <stdio.h> 
#include <stdlib.h> 

int test(unsigned char **q) 
{ 
    *q = (unsigned char *) malloc(250); 
    if(*q == NULL) 
    { 
     printf("\n Error: failed to allocate memory"); 
     return -1; 
    } 
// *q[0] = 10; 
// *q[1] = 10; 
    *q[2] = 10; 

    return 0; /* Returns 0 on success, non-zero value on failure */ 
} 

int main(void) 
{ 
    unsigned char *p; 

// printf("\n &p = %u", &p); 
    int result = test(&p); 

// printf("\n p[2] = %d", p[2]); 
    return 0; 
} 

Если я пишу что-то в *q[0] или *q[1], нет никакой ошибки. Но когда я пытаюсь что-то написать *q[2], он дает «Ошибка сегментации (сбрасывание ядра)».

Также я получаю все данные как 0, используя p[ ], за исключением p[0].

Что не так с этим кодом?

+2

Добро пожаловать в переполнение стека! [Пожалуйста, ознакомьтесь с этим обсуждением, почему бы не использовать возвращаемое значение 'malloc()' и family в 'C'.] (Http://stackoverflow.com/q/605845/2173917). –

+6

'* q [2] = 10;' должно быть '(* q) [2] = 10;'. – mch

+0

Недостаток знаний! = Typo. Голосование для повторного открытия. Не стесняйтесь закрываться как обман. –

ответ

0

Вместо этого неправильного присвоения

*q[2] = 10; 

, что связано с оператором приоритета, эквивалентной

*(q[2]) = 10; 

и, как результат разыменованного указатель Q [2] является неинициализированным и имеет неопределенное значение. Вы должны написать либо как

(*q)[2] = 10; 

или даже просто как

q[0][2] = 10; 

Другой способ ввести промежуточную переменную и использовать его для инициализации элементов массива. Например,

char *p = *q; 

p[2] = 10; 

Это позволяет избежать подобных ошибок с помощью указателей.

+0

И не делайте ошибки при добавлении промежуточной переменной p перед распределением памяти. – mk09

2

Из-за отсутствия явных скобок и, таким образом, по умолчанию operator precedence вступает в силу, ваше выражение интерпретируется неправильно.

Для выражения как

*q[2] 

он интерпретируется как

*(q[2]) 

который является то, что вы не хотите здесь. Арифметика указателей отличия типа данных, таким образом, x + 1 или x[1] будет иметь различные результатов, когда

  • x имеет типа char *
  • x имеет типа char **.

Вам нужно написать

(*q)[2] = 10; 

явно, первый в разыменовать q получить char *, а затем использовать индексацию, чтобы получить символ.

2

Из-за приоритета оператора на языке C, для *q[2], [] Оператор оценивается перед оператором *.

Таким образом, *q[2] - это значение по адресу q + 2. То, что вы хотите, это значение в *q + 2. Поэтому используйте (*q) + 2.

*q[0] или *q[1] не дал ошибки сегментации, так как адреса q + 0, q + 1 были выделены для вашего процесса.

Адрес q + 2 не был предоставлен вашему процессу и, следовательно, ошибка сегментации.

+0

Спасибо. В вашем ответе объясняются все ошибки, которые я получил. Влад из Москвы дал разные способы избежать этих ошибок. Поэтому я принял этот ответ. – mk09