2014-10-28 5 views
1

Мне не хватает фундаментальной точки при передаче значений.Передача значений функции

В моем коде, я написал этот прототип/функции:

void drawFont (char A[],unsigned char length, char x1, char y1, uint16 FGcolor); 

я вызываю функцию с помощью вызова, как это:

drawFont ("William",7,15,25,YEL,0); 

или

drawFont ("W",1,15,25,YEL,0); 

Оба эти отлично работайте в коде. Если я рассмотрю A [0] в функции, я увижу значение «57», представляющее ASCII 'W'. Все хорошо и хорошо.

Мой вопрос/проблема: Когда я пытаюсь повторить «W», используя значение ASCII вместо строкового представления, мой код не Пример:

drawFont (57,1,15,25,YEL,0); 

Значение A [0] в код равен: 0, но адрес A равен 57. Так почему-то компилятор предполагает, что я хочу передать указатель? Я смущен, почему он прошел строку отлично, но не значение?

Заранее благодарен программисту-новичку C.

+0

«как-то компилятор предполагает, что я хочу передать указатель» - это * точно *, что 'char A []' находится в контексте этого списка параметров. Отладчик и/или 'printf («% p:% s », A, A);' вверху 'drawFont' для вашего Первые два примера, скорее всего, будут интересными. – WhozCraig

+0

Не совсем. отладчик, вот как я знаю, что происходит. Я действительно хочу, чтобы printf был доступен мне! Это будет упрощать вещи. Но это микроконтроллер, поэтому большинство моих вопросов являются теоретическими, так как выход трудно тестировать. Обычно мне приходится изучать ценности и спрашивать: «Почему?». – Cartoondog

+0

прототип показывает 5 параметров, однако каждая из выписок показывает 6 параметров. Компилятор должен был выпустить предупреждающее сообщение (как минимум). для каждого из вызовов. вы использовали параметр в компиляции что-то вроде (для компилятора GCC) -Wall? – user3629249

ответ

1

Прототип для функции заявляет, что первый параметр является указателем на символ:

void drawFont (char A[],...); 

Если вы передаете целое число, вы нарушаете правила. Компилятор должен предупредить об этом.Шахта выдает предупреждение о следующем коде на линии с func(57):

void func(char a[]) 
{ 
} 

char arr[] = {87,84,70}; 

int main() 
{ 
    func(57); 
    func("W"); 
    func(arr); 
} 
x.c(9) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int' 
x.c(9) : warning C4024: 'func' : different types for formal and actual parameter 1 

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

PUBLIC _arr 
_DATA SEGMENT 
_arr DB  057H    ;Here's the char array at an address in memory. 
     DB  054H 
     DB  046H 
     ORG $+1 
$SG1297 DB  'W', 00H ;Here's the "W" at an address in memory (nul-terminated) 
_DATA ENDS 

; 9 :  func(57); 

    00003 6a 39   push 57     ; Push 57 as the address, WRONG! 
    00005 e8 00 00 00 00 call _func 
    0000a 83 c4 04   add  esp, 4 

; 10 :  func("W"); 

    0000d 68 00 00 00 00 push OFFSET $SG1297  ; Push the address of the string. 
    00012 e8 00 00 00 00 call _func 
    00017 83 c4 04   add  esp, 4 

; 11 :  func(arr); 

    0001a 68 00 00 00 00 push OFFSET _arr   ; Push the address of the array. 
    0001f e8 00 00 00 00 call _func 
    00024 83 c4 04   add  esp, 4 

Код ожидает перехода на адрес для чтения символов. Кто знает, что в адрес 57.

+0

Спасибо за ответ. Ваш параметр массива функций объявлен как косвенный, я не знаю, почему именно ваш компилятор жалуется. Мой не дает предупреждения и не объявляется таковым. Кроме того, char - 8-битное число/небольшое целое число, так сказать, компилятор не заботится о том, как вы его используете. Моя проблема в том, почему «W» попадает в массив символов как 57, но буквальный 57 заканчивается как адрес/указатель. Итак, сформулировал другой путь, если бы я хотел подтолкнуть множество литералов в этот массив, как бы я это сделал? – Cartoondog

+0

Нет никакой разницы между объявлением 'char * a' и' char a [] '. Он генерирует точно такой же код и даже ту же самую ошибку (включая символ «char *» в сообщении. Я обновлю его в соответствии с вашим объявлением, но это два способа объявить, что ожидается 'char' _pointer_. –

+0

Вы не можете передать '57' функции, ожидающей указателя, без проблем. То, что ваш компилятор даже не предупреждает вас о проблеме, является неудачным. Возможно, проверьте, что вы можете увеличить уровень предупреждения с помощью параметра командной строки? –

1

значение из A[] фактически является указателем, такие как &A[0] (вы можете переписать функцию, используя char *A вместо char A[]

Это адрес первого слота, не то, что хранится в нем . В ячейке памяти, на которую указывает указатель, существует значение 57. Когда вы пишете функцию с атрибутом char или параметром указателя char, вы сообщаете компилятору: я передам вам адрес памяти. Перейдите на этот адрес и запустите считывая каждый символ (число), пока вы не достигнете нулевого байта, затем остановите.

Но когда вы передаете буквальное целое число 57 в качестве аргумента, это не допустимый указатель на массив символов. Вам не хватает уровня косвенности.

Итак, давайте предположим, что ваш символ A [] находится в 0xfeaa0011

В оперативной памяти в 0xfeaa0011 -> "William" (или 52, ...)

Правильный вызов drawFont() на самом деле выглядит drawFont (0xfeaa0011, 1, 15, 25, YEL, 0)

Таким образом, вы видите, что замена указателя на 57 не то же самое.

+0

Я понимаю, что вы говорите о косвенности указателя. То, чего я все еще не хватает; переданное значение char - это значение (в конце), поэтому как бы я мог «передать» литерал 57 правильно, или есть оператор, который инструктирует компилятор обрабатывать литерал (57) как литерал, а не ссылка указателя? – Cartoondog

+0

Вы все еще не подключаете что-то. Вы можете сохранить 57 где-нибудь в адресе памяти, а затем передать адрес 57 в функцию. Вот что такое массив. Речь идет не о буквальном vs указателе, это буквально адрес памяти в одном случае по сравнению с небольшим целым числом (57) в другом. Эта функция будет думать, что вы имели в виду адрес 57 – codenheim

+0

Единственный способ добавить уровень косвенности к 57 - хранить его где-то. Само по себе 57 является буквальным или «немедленным» значением, которое даже не позволяет вам принимать его адрес. – codenheim

2

Если вы передаете

drawFont (57,1,15,25,YEL,0); 

вы будете Doming такой же, как

drawFont ('W',1,15,25,YEL,0); 

который только один символ. Для функции требуется массив символов, поэтому это неверно.

0

Ваша функция требует в качестве аргумента строки (char []). Когда вы проходите «Уильям», это интерпретируется как строка, это нормально. Когда вы проходите «W» это также интерпретируется как строка:

string[2] = { 'W' + 0 } //notice the null byte following your char 

Это потому, что вы использовали двойные кавычки "вместо одинарные кавычки. Поэтому, проходящей 57 или„W“рассматривается как единый char, а не char []/string, который затем дает вам ошибку, так как ваша функция ожидает char [], и вы дали ей char.

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