2015-07-21 1 views
4

Как сделать эту работу:список Инициализатор передается в качестве параметра функции для массива

void foo(uint8_t a[]) { ... } 

foo({0x01, 0x02, 0x03}); 

Это дает мне ошибку:

error: cannot convert '<brace-enclosed initializer list>' to 'uint8_t* {aka unsigned char*}' for argument '1' 
                ^
+0

Проблема была бы яснее, если бы вы избежали запутывающего '' параметра uint8_t [] 'parameter" и вместо этого записывали более точный 'uint8_t *'. :) –

+0

Извините, я обычно использовал форму указателя, но мне было интересно, может ли компилятор выполнить какую-то магию, о которой я не знал, вместо того, чтобы использовать синтаксис массива. – Timmmm

+0

Нет, 100% эквивалентность. –

ответ

2

Ответы до сих пор не рассматривались основные проблемы с вопрос: в подписи

void foo(uint8_t a[]) 

a не является массив, а указатель на uint8_t. Это несмотря на то, что объявление a делает его похожим на массив. Это даже указал сообщением об ошибке:

cannot convert '<brace-enclosed initializer list>' to 'uint8_t* {aka unsigned char*}' 

Таким образом, так же, как вы не можете сделать это:

uint8_t *a = {0x01, 0x02, 0x03}; // Eek! Error 

Вы не можете позвонить foo({0x01, 0x02, 0x03}); С помощью данной подписи.

Предлагаю вам потратить некоторое время на чтение массивов в стиле C и их not first-class citizens на C++.

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

void foo(std::array<uint8_t, 3> const &a); 
4

Вы не можете. Просто построить

uint8_t a[] = {0x01, 0x02, 0x03}; 

и вызвать foo(a).

Или просто используйте std::array, это, вероятно, лучше.

6

Это работает для меня, я должен был изменить сигнатуру, но на самом деле это лучше в моем случае, как это статически проверяет длину массива:

void foo(std::array<uint8_t, 3> a) { /* use a.data() instead of a */ } 

foo({0x01, 0x02, 0x03}); // OK 

foo({0x01, 0x02}); // Works, at least on GCC 4.9.1. The third value is set to zero. 

foo({0x01, 0x02, 0x03, 0x04}); // Compilation error. 
+1

C-образные массивы сосать на * все *. Всегда используйте std :: array над ними, если это возможно. – Puppy

+1

Возможно, вы можете использовать шаблон, например 'template void foo (std :: array a) {/*...*/}' ... (Я раньше не пробовал ...) – Shindou

+2

@ В этом случае параметр 'size' не может быть выведен. – ForEveR

3

Это:

void foo(uint8_t a[]) { ... } 

это функция, которая принимает uint8_t*, а не массив - массивы распались к указателям при использовании в качестве аргументов функции. Проблема заключается в том, что список инициализаторов (например, {0x01, 0x02, 0x03}) не может быть преобразован в uint8_t*.

Если то, что вы хотите передать произвольное число uint8_t с до foo, простое решение заключается в использовании нового std::initializer_list

void foo(std::initializer_list<uint8_t> a) { ... } 

foo({0x01, 0x02, 0x03, 0x04, 0x05}); // OK - a has 5 elems in it 

Или вы могли бы взять VARIADIC пакет и построить массив из него изнутри :

template <typename... Args, 
      typename = std::enable_if_t< 
       all_true<std::is_convertible<Args, uint8_t>::value...> 
       >> 
void foo(Args... elems) { 
    uint8_t a[] = {elems...}; 
    // ... 
} 

Это имеет несколько иное использование:

foo({0x01, 0x02, 0x03}); // error 
foo(0x01, 0x02, 0x03; // OK - a has 3 elems in it 
0

foo(std::array<uint8_t, 3>{0x01, 0x02, 0x03}.data());

+0

std :: array создается перед функцией и живет до тех пор, пока функция не вернется. –

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