Не могу понять исходный код на C, и он не компилируется в GCC, но в Visual C ++ - PullRequest
4 голосов
/ 31 января 2011

В GCC я получил следующую ошибку:

aes.c: В функции 'copy_block':aes.c: 278: ошибка: в качестве операнда приращения требуется lvalueaes.c: 278: ошибка: lvalue требуется в качестве операнда приращения

Это фрагмент кода:

static void copy_block( void * d, void *s, uint_8t nn )
{
    while( nn-- )
        *((uint_8t*)d)++ = *((uint_8t*)s)++;
}

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

Может быть, у кого-то есть идея, как мне изменить исходный код, чтобы он был компилируемым в GCC, или у кого-то есть идея, что здесь происходит подробно,Для меня это кажется странным из-за разыменования значения левой руки, но почему-то оно отлично работает в Visual C ++.

Это небольшая устаревшая программа, которую я должен перенести на Linux-машину.

заранее благодарю за помощь.

Ответы [ 7 ]

6 голосов
/ 31 января 2011

Попробуйте:

#include <string.h>
static void copy_block( void * d, void *s, uint_8t nn ) {
  memcpy(d, s, (size_t)nn);
}

То, что там делается, не хорошо.

5 голосов
/ 31 января 2011

Это должно сделать это:

static void copy_block(void *d, void *s, uint_8t nn)
{
    uint_8t *ud = (uint_8t *)d;
    uint_8t *us = (uint_8t *)s;

    while (nn--)
    {
        *ud = *us;
        ++ud;
        ++us;
    }
}

Это также намного более читабельно.

3 голосов
/ 31 января 2011

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

uint8_t *da = d, *sa = s;
while(nn--) *da++ = *sa++;

Два других примечания:

  • nn должно быть гораздо больше uint8_t и, вероятно, size_t.
  • С этим изменением эта функция называется memcpy и находится (вероятно, более эффективно) в вашей стандартной библиотеке (в string.h, я полагаю).
3 голосов
/ 31 января 2011

Это какой-то серьезно волосатый код. Похоже, что есть проблема с правилами приоритета в подвыражениях * (указатель) ++. (что Visual C ++ допускает, что это где-то между чудом и ошибкой) Кажется, это просто (ужасно) переопределение memcpy, поэтому я предлагаю вам использовать стандартную версию:

memcpy(d, s, nn);

Я предлагаю провести быстрый тест по характеристике в Visual C ++, чтобы убедиться, что две версии кода на самом деле делают одно и то же (как они, кажется). Возможно, вы полагаетесь на причудливый крайний случай в компиляторе.

2 голосов
/ 31 января 2011

Почему все предполагают, что вы всегда должны использовать библиотечные функции, когда это возможно?

В системах с высоким уровнем целостности вы хотите избегать библиотечных функций, таких как чума, потому что как толькоВы включаете заголовок библиотеки, вы должны проверить весь исходный код внутри него, убедившись, что он не содержит ошибок.Проверка всего string.h и запуск его с помощью инструментов статического анализа и т. Д. Не является забавной задачей.

Для всех не-программистов, вот версия, совместимая с MISRA-C: 2004, которую вы можете использовать.

void gpfunc_memcpy (void* s1, const void* s2, uint16 n)
{
        uint8* u_s1 =       (uint8*) s1;
  const uint8* u_s2 = (const uint8*) s2;

  while(n != 0)
  {
    *u_s1 = *u_s2;

    ++u_s1;
    ++u_s2;  
    --n;
  }
}
1 голос
/ 31 января 2011

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

static void copy_block( void * d, void *s, uint_8t nn )
{
    while( nn-- )
        *((uint_8t*)d++) = *((uint_8t*)s++);
}

В качестве бонусного совета используйте memcpy ... намного быстрее!

0 голосов
/ 31 января 2011

Должно быть:

static void copy_block( void * d, void *s, uint_8t nn )
{
    while( nn-- )
        (*((uint_8t*)d))++ = (*((uint_8t*)s))++;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...