2015-12-11 4 views
-3

Имеет некоторые проблемы с указателем на массив и передачей его функции. Всякий раз, когда я передаю указатель, передается только первый элемент, и я не могу получить доступ к другим элементам в отладке.C++ Указатель на массив

Type* variable[2]; 

void myFunction(Type* var); 
+0

Вы должны указать размер рядом с указателем. Нет никакого способа обойти это, кроме использования ['array_view'] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3851.pdf), который может быть включен в будущее STL –

+0

'variable' - это массив указателей, а не указатель на массив. Чтобы оставить 'переменную' неизменной,' myFunction' должен быть переопределен для принятия аргумента 'Type **', – Paulo1205

+0

Почему 'variable' является массивом' Type * ', является' Type' polymorphic? – fredoverflow

ответ

2

Использование std::array вместо этого, он таскает такие детали для вас.

std::array<Type*, 2> variable; 

void myFunction(std::array<Type*, 2>&); 
+1

Вы не можете иметь произвольные массивы длины с помощью 'std :: array'. – Sorin

+0

@Sorin Что это касается вопроса? –

+0

Он работает в этом конкретном случае, потому что вы знаете размер массива во время компиляции. Обычно это не так. Неясно, является ли пример примером или фактическим вариантом использования. 'std :: vector' был бы более общим. – Sorin

0

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

Элементы этого массива

Type* variable[2]; 

имеют тип Type *

Так передать указатель на первый элемент массива в функцию функция должна быть объявлена ​​как

void myFunction(Type* *var); 

или

void myFunction(Type* var[]); 

Эти объявления эквивалентны, потому что неявно параметр настраивается на указатель на объект типа T*.

Вы можете представить это следующим образом. Если у вас есть массив типа U

U a[N]; 

затем «указатель на массив» будет выглядеть

U *p = a; 

Если U в свою очередь, определяется как

typedef T* U; 

то есть

T* a[N]; 
T* *p = a; 

Strictly sp eaking указатель в массив будет выглядеть

Type* variable[2]; 
Type * (*p)[2] = &variable; 

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

0

Как я уже сказал в комментарии, variable представляет собой массив указателей, а не указатель на массив.

Чтобы оставить без изменений, variablemyFunction должен быть повторно объявлен принять Type ** аргумент, так что вы можете назвать его как myFunction(variable).

не

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

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

void myFunction(Type **arr_to_ptrs, size_t ptr_count); 

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

#define myFunction_1arg(x) myFunction(x, sizeof x/sizeof x[0]) 

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

С C++, почти каждое использование родных массивов может быть в более общем и безопасно решать с std::vector и менее в целом с std::array.

Однако, если вы действительно хотите придерживаться встроенных массивов, вы все равно можете использовать некоторые функции C++. Программа ниже может дать вам представление.

#include <iostream> 
#include <cstddef> 

const char a[]="ab";      // array 
const char *ap[]={"aa", "bb", nullptr}; // array of pointers 
const char (*pa)[3]=&a;     // pointer to array of three elements 

// This function takes an array (by reference). 
template <typename T, size_t sz> void f(T (&arr)[sz]){ 
    std::cout << "array-templated f(): addr=" << static_cast<const void *>(arr) << ", size=" << sz << '\n'; 
} 

// This function takes a pointer (by lvalue reference). 
template <typename T> void f(T *const &arr){ 
    std::cout << "lvalue-ref-pointer-templated f(): addr=" << static_cast<const void *>(arr) << ", unspecified size\n"; 
} 

// This function takes a pointer (by rvalue reference). 
template <typename T> void f(T *const &&arr){ 
    std::cout << "rvalue-ref-pointer-templated f(): addr=" << static_cast<const void *>(arr) << ", unspecified size\n"; 
} 

// This function takes a pointer and its size (by value). 
template <typename T> void f(T *arr, size_t sz){ 
    std::cout << "pointer-templated f(): addr=" << static_cast<const void *>(arr) << ", manual size=" << sz << "\n"; 
} 


int main(){ 
    f(a); 
    f(ap); 
    f(pa); 
    std::cout << '\n'; 

    f(0+a); 
    f(0+ap); 
    f(0+pa); 
    std::cout << '\n'; 

    f(a, 1);  // You can lie here, but you shouldn't 
    f(ap, 10); // You can lie here, but you shouldn't 
    f(pa, 100); // You can lie here, but you shouldn't 
    std::cout << '\n'; 

    f(0+a, 1);  // You can lie here, but you shouldn't 
    f(0+ap, 10); // You can lie here, but you shouldn't 
    f(0+pa, 100); // You can lie here, but you shouldn't 
    std::cout << '\n'; 

    auto *p=a; 
    auto *pp=ap; 
    auto *pa2=pa; // pa2 and pa are the same type: pa is already a pointer 
    f(p); 
    f(pp); 
    f(pa2); 
    std::cout << '\n'; 

    f(p, 1);  // You can lie here, but you shouldn't 
    f(pp, 10); // You can lie here, but you shouldn't 
    f(pa2, 100); // You can lie here, but you shouldn't 
    std::cout << '\n'; 

    f(0+p, 1);  // You can lie here, but you shouldn't 
    f(0+pp, 10); // You can lie here, but you shouldn't 
    f(0+pa2, 100); // You can lie here, but you shouldn't 
} 

Выход для этой программы несколько похож на приведенный ниже.

array-templated f(): addr=0x40106d, size=3 
array-templated f(): addr=0x602070, size=3 
lvalue-ref-pointer-templated f(): addr=0x40106d, unspecified size 

rvalue-ref-pointer-templated f(): addr=0x40106d, unspecified size 
rvalue-ref-pointer-templated f(): addr=0x602070, unspecified size 
rvalue-ref-pointer-templated f(): addr=0x40106d, unspecified size 

pointer-templated f(): addr=0x40106d, manual size=1 
pointer-templated f(): addr=0x602070, manual size=10 
pointer-templated f(): addr=0x40106d, manual size=100 

pointer-templated f(): addr=0x40106d, manual size=1 
pointer-templated f(): addr=0x602070, manual size=10 
pointer-templated f(): addr=0x40106d, manual size=100 

lvalue-ref-pointer-templated f(): addr=0x40106d, unspecified size 
lvalue-ref-pointer-templated f(): addr=0x602070, unspecified size 
lvalue-ref-pointer-templated f(): addr=0x40106d, unspecified size 

pointer-templated f(): addr=0x40106d, manual size=1 
pointer-templated f(): addr=0x602070, manual size=10 
pointer-templated f(): addr=0x40106d, manual size=100 

pointer-templated f(): addr=0x40106d, manual size=1 
pointer-templated f(): addr=0x602070, manual size=10 
pointer-templated f(): addr=0x40106d, manual size=100 
Смежные вопросы