2017-02-11 2 views
3

У меня этот код, функция strtol получает двойной указатель, и предполагается, что строка «prueba» является указателем, указывающим на адрес памяти первого элемента строки (который является тем же адресом памяти вся цепь), то это, как если бы оно было пропусканием реж указателя, я не знаю, если я объясню, во всяком случае это не работает:/выдает предупреждение здесьПочему я не могу передать адрес цепочки? Strtol

ret = strtol(str, &prueba, 10); 

длинный ИНТ strtol (const char * str, char ** endptr, int base)

strtol преобразует начальную часть строки в str в длинный int va в соответствии с данной базой. «endptr» his - это ссылка на объект типа char *, значение которого задается функцией следующим символом в str после численного значения.

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

int main() 
{ 
    char str[30] = "2030300 This is test"; 
    char prueba[20]; 
    char *ptr; 
    long ret; 
    printf("\nLa cadena inicial es: %c%s%c\n",34,str,34); 


    ret = strtol(str, &ptr, 10); 
    printf("\nThe number(unsigned long integer) is %ld\n", ret); 
    printf("String part is |%s|\n", ptr); 

    ret = strtol(str, &prueba, 10); 
    printf("\nProbando: %c%s%c\n",34,prueba,34); 

    return(0); 
+0

'& prueba' является указателем на массив из 20' char's. –

+0

'& prueba' не является символом' char ** '. Это 'char (*) [20]'. То есть, это указатель на массив. Вы должны объявить как: 'char * prueba;' – kaylum

+0

, но если я объявляю char * prueba, это указатель на массив.как char prueba [20] – EmiliOrtega

ответ

3

Я вижу один большое заблуждение здесь необходимо решить: указателей не так же, как массивы. Указатель - это вещь, которая говорит вам, как найти что-то еще; что что-то еще может быть единственной вещью или достаточно неинициализированным пространством для хранения вещи или кучей из них в блоке. Массив - это блок вещей, и очень точно не указатель на блок вещей. То, что вы можете поставить [0] после каждого, и в конечном итоге вещь не имеет отношения к этому обсуждению.

Почему он не распадается на char *, который представляет адрес его первого элемента, как если бы он передавался функции или даже присваивался? Поскольку стандарт C говорит, что этого не произойдет - он определяет только три исключения из правила «распада массивов в указатели на их первый элемент». Один из них - когда этот массив является операндом оператора &, так что вы получаете указатель на предмет, о котором вы спрашиваете, а не что-то еще, что, хотя и связано, не так.

Из-за этого вы не пропустите char ** в strtol. Вы передаете указатель на массив. Хотя в некоторых случаях это может быть хорошо, его здесь нет, так как функция хочет поставить char *, где вы говорите, чтобы положить его; если вы попробуете сказать «поместите его в этот char[]», он не собирается делать то, что вы хотите. Он попытается набить char * в ваш char[], и вы получите неопределенное поведение.

Для дальнейшего ознакомления см. Comp.lang.c Вопросы и ответы 6.2 и 6.3.


Да, и кстати, GCC будет предупреждать вас об этом, если вы сказать ему: Пройди -Wincompatible-pointer-types или, еще лучше, что-то вроде -Wall -Werror (в зависимости от рекомендации вашего компилятора), чтобы компилятор - это будет производить предупреждение, которое выглядит примерно так:

/path/to/main.c: In function 'main': 
/path/to/main.c:17:23: warning: passing argument 2 of 'strtol' from incompatible pointer type [-Wincompatible-pointer-types] 
    ret = strtol(str, &prueba, 10); 
        ^
In file included from /usr/include/stdio.h:29:0, 
       from /path/to/main.c:1: 
/usr/include/stdlib.h:166:6: note: expected 'char ** restrict' but argument is of type 'char (*)[20]' 
long _EXFUN(strtol,(const char *__restrict __n, char **__restrict __end_PTR, int __base)); 

точный текст может отличаться, конечно, но суть его будет тем же.

+0

Как вы «попросили» об этом: вы не можете применить индекс-оператор (resp, + или -) к массиву. Это просто ** выглядит ** как-если (звучит как nit-picking, но как только вы это понимаете, вы понимаете массивы в C). И причина, по которой он не работает (кроме проблемы с типом), - это просто потому, что вы не можете изменить значение самого массива (массив не имеет значения сам по себе, как указатель, это всего лишь элементы). Наконец: на информационной странице C перечислены рекомендуемые предупреждения. К ним относятся '-Wall -Wextra -Wconversion'. Лично я бы порекомендовал еще целую кучу. – Olaf

+0

'long _EXFUN (...' ?? Huh, никогда не видел такого сообщения. – Olaf

+0

@Olaf Да, я был немного менее строго правильным (т.е. я говорил из синтаксиса POV - 'int a [2]; [0]; 'действительный синтаксис, как и' int * a; a [0]; '. Я думаю, что сходство является причиной путаницы, но я сделаю это явным. WRT, почему он не работает - восклицает, да, я должен определенно сделать это явным. Это то, к чему я привык, «поместив его в этот« char [] '», но он ... на самом деле не получился. WRT 'long _EXFUN' - - это буквально то, что вывел мой компилятор, когда я скомпилировал код. Я не знаю, откуда он пришел. –

Смежные вопросы