Как передать постоянный литерал массивов функции, которая берет указатель, не используя переменный C/C++?

Две опции приходят на ум:

1) использование len() или lenb(), чтобы обнаружить, существуют ли какие-либо данные в переменной:

if not lenb(rs("myField"))=0 then...

2) используют функцию, которая возвращает булевскую переменную:

if not isNothing(rs("myField")) then...

, где isNothing() функция как так:

function isNothing(vInput)
    isNothing = false : vInput = trim(vInput)
    if vartype(vInput)=0 or isEmpty(vInput) or isNull(vInput) or lenb(vInput)=0 then isNothing = true : end if 
end function
29
задан Ciro Santilli 新疆改造中心法轮功六四事件 10 May 2016 в 17:48
поделиться

8 ответов

Вы можете сделать это в C99 (но не ANSI C (C90) или любой текущий вариант C ++) с составными литералами . См. Подробности в разделе 6.5.2.5 стандарта C99. Вот пример:

// f is a static array of at least 4 floats
void foo(float f[static 4])
{
   ...
}

int main(void)
{
    foo((float[4]){1.0f, 2.0f, 3.0f, 4.0f});  // OK
    foo((float[5]){1.0f, 2.0f, 3.0f, 4.0f, 5.0f});  // also OK, fifth element is ignored
    foo((float[3]){1.0f, 2.0f, 3.0f});  // error, although the GCC doesn't complain
    return 0;
}

GCC также предоставляет это как расширение C90. Если вы компилируете с помощью -std = gnu90 (по умолчанию), -std = c99 или -std = gnu99 , он будет компилироваться; если вы скомпилируете с -std = c90 , этого не произойдет.

33
ответ дан 28 November 2019 в 01:20
поделиться

Это обозначено как C, так и C ++, поэтому вы получите совершенно разные ответы.

Если вы ожидаете четыре параметра, вы можете сделать это:

void foo(float f[])
{
    float f0 = f[0];
    float f1 = f[1];
    float f2 = f[2];
    float f3 = f[3];
}

int main(void)
{
    float f[] = {1, 2, 3, 4};
    foo(f);
}

Но это скорее небезопасно, так как вы можете сделать это случайно:

void foo(float f[])
{
    float f0 = f[0];
    float f1 = f[1];
    float f2 = f[2];
    float f3 = f[3];
}

int main(void)
{
    float f[] = {1, 2}; // uh-oh
    foo(f);
}

Обычно лучше оставить их как отдельные параметры. Поскольку вам все равно не следует использовать необработанные массивы, вы можете сделать следующее:

#include <cassert>
#include <vector>

void foo(std::vector<float> f)
{
    assert(f.size() == 4);

    float f0 = f[0];
    float f1 = f[1];
    float f2 = f[2];
    float f3 = f[3];
}

int main(void)
{
    float f[] = {1, 2, 3, 4};
    foo(std::vector<float>(f, f + 4)); // be explicit about size

    // assert says you cannot do this:
    foo(std::vector<float>(f, f + 2));
}

Улучшение, но не очень. Вы можете использовать boost :: array , но вместо ошибки из-за несоответствия размера они инициализируются значением 0:

#include <boost/array.hpp>

void foo(boost::array<float, 4> f)
{
    float f0 = f[0];
    float f1 = f[1];
    float f2 = f[2];
    float f3 = f[3];
}

int main(void)
{
    boost::array<float, 4> f = {1, 2, 3, 4};
    foo(f);

    boost::array<float, 4> f2 = {1, 2}; // same as = {1, 2, 0, 0}
    foo(f2);
}

Все это будет исправлено в C ++ 0x, когда добавлены конструкторы списка инициализаторов:

#include <cassert>
#include <vector>

void foo(std::vector<float> f)
{
    assert(f.size() == 4);

    float f0 = f[0];
    float f1 = f[1];
    float f2 = f[2];
    float f3 = f[3];
}

int main(void)
{
    foo({1, 2, 3, 4}); // yay, construct vector from this

    // assert says you cannot do this:
    foo({1, 2});
}

И, вероятно, boost :: array , а также:

#include <boost/array.hpp>

void foo(boost::array<float, 4> f)
{
    float f0 = f[0];
    float f1 = f[1];
    float f2 = f[2];
    float f3 = f[3];
}

int main(void)
{
    foo({1, 2, 3, 4});

    foo({1, 2}); // same as = {1, 2, 0, 0} ..? I'm not sure,
                 // I don't know if they will do the check, if possible.
}
19
ответ дан 28 November 2019 в 01:20
поделиться

Вы можете создать составной литерал:

function ((float[2]){2.0, 4.0});

Хотя я не уверен, почему вы хотите столкнуться с этой проблемой. Это не разрешено ISO.

Как правило, таких сокращений следует избегать в пользу удобочитаемости во всех случаях; лень - не самая лучшая привычка исследовать (личное мнение, конечно)

4
ответ дан 28 November 2019 в 01:20
поделиться

Технически вы можете использовать ссылку на массив, но я думаю, вы все равно не можете создать список анонимных инициализаторов.

void func(int (&bla)[4])
{
    int count = sizeof(bla)/sizeof(bla[0]);
    // count == 4
}

int bla[] = {1, 2, 3, 4};
func(bla);

int bla1[] = {1, 2};
func(bla1); // <-- fails

Для C ++, посмотрите на boost :: assign . Довольно удобный способ наполнения контейнеров STL.

3
ответ дан 28 November 2019 в 01:20
поделиться

Плохие новости в том, что для этого нет синтаксиса. Хорошая новость заключается в том, что это изменится со следующей официальной версией стандарта C ++ (которая должна выйти в ближайшие год или два). Новый синтаксис будет выглядеть точно так, как вы описали.

2
ответ дан 28 November 2019 в 01:20
поделиться

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

function(char *);
function("mystring");

обрабатывается компилятором как

char * some_pointer = "mystring";
function(char *);
function(some_pointer);

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

0
ответ дан 28 November 2019 в 01:20
поделиться

К сожалению, он работает только с массивами символов:

void func2(char arg[]) {
}

int main()
{   
    func2("hello");
    return 0;
}
0
ответ дан 28 November 2019 в 01:20
поделиться

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

// roughly
template <typename C>
class Builder {
public:
   template <typename T>
   Builder(const T & _data) { C.push_back(_data); }
   template <typename T>
   Builder& operator()(const T & _data) { 
       C.push_back(_data);
       return *this;
    }
   operator const C & () const { return data; }
private:
   C data;

};

таким образом, вы можете использовать класс как

foo (const std :: vector & v);

foo (Builder (1) (2) (3) (4));

0
ответ дан 28 November 2019 в 01:20
поделиться