ни один экземпляр шаблона функции не соответствует списку аргументов [duplicate]

Вы также можете проверить, не работает ли $result так, как до этого, перед выполнением массива fetch

$username = $_POST['username'];
$password = $_POST['password'];
$result = mysql_query('SELECT * FROM Users WHERE UserName LIKE $username');
if(!$result)
{
     echo "error executing query: "+mysql_error(); 
}else{
       while($row = mysql_fetch_array($result))
       {
         echo $row['FirstName'];
       }
}
282
задан Peter Mortensen 4 November 2015 в 06:35
поделиться

8 ответов

Говорят, что массивы «распадаются» на указатели. Массив C ++, объявленный как int numbers [5], не может быть перенаправлен, т. Е. Вы не можете сказать numbers = 0x5a5aff23. Что еще более важно, термин «распад» означает потерю типа и размерности; numbers распадаются на int*, теряя информацию о размерности (число 5), и тип больше не int [5]. Посмотрите здесь случаи, когда распад не происходит .

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

Три способа передачи в массиве 1:

void by_value(const T* array)   // const T array[] means the same
void by_pointer(const T (*array)[U])
void by_reference(const T (&array)[U])

Последние два будут давать правильный sizeof, в то время как первый не будет, так как аргумент массива распался для назначения параметру.

1 Константа U должна быть известна во время компиляции.

211
ответ дан Community 25 August 2018 в 02:52
поделиться

tl; dr: Когда вы используете массив, который вы определили, вы фактически будете использовать указатель на его первый элемент.

Таким образом:

  • Когда вы пишете arr[idx], вы действительно просто говорите *(arr + idx). Функции
  • никогда не принимают массивы в качестве параметров, а только указатели, даже если вы указываете параметр массива.

Сортировка исключений из этого правила:

  • Вы можете передавать массивы фиксированной длины в функции в пределах struct.
  • sizeof() дает размер, по массиву, а не по размеру указателя.
0
ответ дан einpoklum 25 August 2018 в 02:52
поделиться

«Распад» относится к неявному преобразованию выражения из типа массива в тип указателя. В большинстве случаев, когда компилятор видит выражение массива, он преобразует тип выражения из «N-element array of T» в «указатель на T» и устанавливает значение выражения в адрес первого элемента массива , Исключениями этого правила являются когда массив является операндом либо операторов sizeof, либо &, либо массив является строковым литералом, который используется в качестве инициализатора в объявлении.

Предположим, что следующий код:

char a[80];
strcpy(a, "This is a test");

Выражение a имеет тип «80-элементный массив символов», а выражение «This is a test» имеет тип «16-элементный массив char» (в C; в C ++ строковые литералы - это массивы const char). Однако в вызове strcpy() ни одно из выражений не является операндом sizeof или &, поэтому их типы неявно преобразуются в «указатель на символ», а их значения устанавливаются на адрес первого элемента в каждый. То, что strcpy() получает, - это не массивы, а указатели, как показано в его прототипе:

char *strcpy(char *dest, const char *src);

Это не то же самое, что указатель массива. Например:

char a[80];
char *ptr_to_first_element = a;
char (*ptr_to_array)[80] = &a;

Оба ptr_to_first_element и ptr_to_array имеют одинаковое значение ; базовый адрес. Тем не менее, они являются разными типами и обрабатываются по-разному, как показано ниже:

a[i] == ptr_to_first_element[i] == (*ptr_to_array)[i] != *ptr_to_array[i] != ptr_to_array[i]

Помните, что выражение a[i] интерпретируется как *(a+i) (которое работает только, если тип массива преобразуется в тип указателя), поэтому оба a[i] и ptr_to_first_element[i] работают одинаково. Выражение (*ptr_to_array)[i] интерпретируется как *(*a+i). Выражения *ptr_to_array[i] и ptr_to_array[i] могут приводить к предупреждениям или ошибкам компилятора в зависимости от контекста; они обязательно сделают неправильную вещь, если вы ожидаете, что они оценят a[i].

sizeof a == sizeof *ptr_to_array == 80

Опять же, когда массив является операндом sizeof, он не преобразуется в указатель тип.

sizeof *ptr_to_first_element == sizeof (char) == 1
sizeof ptr_to_first_element == sizeof (char *) == whatever the pointer size
                                                  is on your platform

ptr_to_first_element - простой указатель на char.

22
ответ дан John Bode 25 August 2018 в 02:52
поделиться

Вот что говорит стандарт (C99 6.3.2.1/3 - Другие операнды - Lvalues, массивы и указатели функций):

За исключением случаев, когда это операнд оператора sizeof или унарный & amp; оператор или является строковым литералом, используемым для инициализации массива, выражение, которое имеет тип '' array of type '', преобразуется в выражение с типом '' указатель на тип '', который указывает на начальный элемент объекта массива и не является lvalue.

Это означает, что в любом случае имя массива используется в выражении, оно автоматически преобразуется в указатель на 1-й элемент массива.

Обратите внимание, что имена функций действуют аналогичным образом, но указатели на функции используются гораздо меньше и гораздо более специализированным способом, так что это не вызывает почти столько же путаницы, как автоматическое преобразование имен массивов в указатели.

Стандарт C ++ (преобразование с преобразованием массива в переменную 4.2) ослабляет требование преобразования к (выделение мое):

lvalue или rvalue типа «массив NT» или «массив неизвестной границы T "можно преобразовать в rvalue типа« указатель на T ».

Таким образом, преобразование не

[gg]. Это также почему в C вам следует избегать использования параметров массива в функции прототипы / определения (по-моему - я не уверен, есть ли какое-либо общее согласие). Они вызывают путаницу и в любом случае являются фикцией - используют параметры указателя, и путаница может не исчезнуть целиком, но, по крайней мере, объявление параметра не лежит.

40
ответ дан Michael Burr 25 August 2018 в 02:52
поделиться

Это когда массив гниет и указывает на: -)

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

6
ответ дан Michael Krelin - hacker 25 August 2018 в 02:52
поделиться

Массивы в C не имеют значения.

Везде, где ожидается значение объекта, но объектом является массив, вместо него используется адрес его первого элемента , с типом pointer to (type of array elements).

В функции все параметры передаются по значению (массивы не являются исключением). Когда вы передаете массив в функции, он «распадается на указатель» (sic); когда вы сравниваете массив с чем-то другим, снова он «распадается на указатель» (sic); ...

void foo(int arr[]);

Функция foo ожидает значение массива. Но в C массивы не имеют ценности! Таким образом, foo получает вместо этого адрес первого элемента массива.

int arr[5];
int *ip = &(arr[1]);
if (arr == ip) { /* something; */ }

В приведенном выше сравнении arr не имеет значения, поэтому он становится указателем. Он становится указателем на int. Этот указатель можно сравнить с переменной ip.

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

arr[42];
/* same as *(arr + 42); */
/* same as *(&(arr[0]) + 42); */

Единственный раз, когда массив не распадается на указатель, это когда он является операндом оператора sizeof, или & amp; оператор («адрес оператора») или как строковый литерал, используемый для инициализации массива символов.

12
ответ дан pmg 25 August 2018 в 02:52
поделиться

Затухание массива означает, что когда массив передается как параметр функции, он обрабатывается тождественно («распадается на») указатель.

void do_something(int *array) {
  // We don't know how big array is here, because it's decayed to a pointer.
  printf("%i\n", sizeof(array));  // always prints 4 on a 32-bit machine
}

int main (int argc, char **argv) {
    int a[10];
    int b[20];
    int *c;
    printf("%zu\n", sizeof(a)); //prints 40 on a 32-bit machine
    printf("%zu\n", sizeof(b)); //prints 80 on a 32-bit machine
    printf("%zu\n", sizeof(c)); //prints 4 on a 32-bit machine
    do_something(a);
    do_something(b);
    do_something(c);
}

Существует два осложнения или исключения для выше.

Во-первых, при работе с многомерными массивами в C и C ++ теряется только первое измерение. Это связано с тем, что массивы сложены в памяти, поэтому компилятор должен знать все, кроме первого измерения, чтобы вычислить смещения в этом блоке памяти.

void do_something(int array[][10])
{
    // We don't know how big the first dimension is.
}

int main(int argc, char *argv[]) {
    int a[5][10];
    int b[20][10];
    do_something(a);
    do_something(b);
    return 0;
}

Во-вторых, на C ++ вы можете используйте шаблоны для вывода размера массивов. Microsoft использует это для C ++-версий функций Secure CRT, таких как strcpy_s , и вы можете использовать подобный трюк, чтобы надежно получить количество элементов в массиве .

1
ответ дан snr 25 August 2018 в 02:52
поделиться

Массивы в основном такие же, как указатели на C / C ++, но не совсем. После преобразования массива:

const int a[] = { 2, 3, 5, 7, 11 };

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

const int* p = a;

вы теряете способность sizeof для подсчета элементов в массиве:

assert( sizeof(p) != sizeof(a) );  // sizes are not equal

Эта потерянная способность называется «распад».

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

77
ответ дан system PAUSE 25 August 2018 в 02:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: