PDA

View Full Version : GCC Intrinsics bswap64 (C Programming)




MorphingDragon
Jul 24, 2012, 04:48 AM
I'm looking at using bswap64 to help speed up string reversing but I'm having issues getting the type system to play nicely.


test.c: In function ‘main’:
test.c:19: warning: cast to pointer from integer of different size
test.c: At top level:
test.c:27: error: conflicting types for ‘storeLong’
test.c:19: note: previous implicit declaration of ‘storeLong’ was here
test.c:40: error: conflicting types for ‘extractLong’
test.c:10: note: previous implicit declaration of ‘extractLong’ was here


This is my current test/play code, it takes "abcdefgh" and prints "hgfedcba":


#include <stddef.h>
#include <stdio.h>
#include <stdint.h>

int main(int argc, char *argv[]) {
// Example Word
char* word = "abcdefgh";

// Get long representation
int64_t num = extractLong(word, 0);

// Print String
printf("%s\n", num);

// Perform ByteSwap
num = __builtin_bswap64(num);

// Store Swap back into string
word = (char*) storeLong(word, 0, num);

// Print String
printf("%s\n", num);

return 0;
}

void storeLong(char* array, size_t off, int64_t val)
{
array[off + 0] = (char)((val & 0xff00000000000000L) >> 56);
array[off + 1] = (char)((val & 0x00ff000000000000L) >> 48);
array[off + 2] = (char)((val & 0x0000ff0000000000L) >> 40);
array[off + 3] = (char)((val & 0x000000ff00000000L) >> 32);
array[off + 4] = (char)((val & 0x00000000ff000000L) >> 24);
array[off + 5] = (char)((val & 0x0000000000ff0000L) >> 16);
array[off + 6] = (char)((val & 0x000000000000ff00L) >> 8);
array[off + 7] = (char)((val & 0x00000000000000ffL));
}

int64_t extractLong(char* array, size_t off)
{
int64_t a = array[off+0] & 0xff;
int64_t b = array[off+1] & 0xff;
int64_t c = array[off+2] & 0xff;
int64_t d = array[off+3] & 0xff;
int64_t e = array[off+4] & 0xff;
int64_t f = array[off+5] & 0xff;
int64_t g = array[off+6] & 0xff;
int64_t h = array[off+7] & 0xff;
return (a<<56 | b<<48 | c<<40 | d<<32 | e<<24 | f<<16 | g<<8 | h);
}



gnasher729
Jul 24, 2012, 06:37 AM
You need a function prototype before calling the function.

So when you call the function without a prototype, you get a warning (which should be an error) and the compiler guesses the prototype. Then later on it complains again because the guess doesn't match the actual function.

And functions not used outside a file should always be static. Makes life a lot easier once your project grows.

And what is %s for? Not for integers of any size.

MorphingDragon
Jul 24, 2012, 06:39 PM
You need a function prototype before calling the function.

So when you call the function without a prototype, you get a warning (which should be an error) and the compiler guesses the prototype. Then later on it complains again because the guess doesn't match the actual function.

And functions not used outside a file should always be static. Makes life a lot easier once your project grows.

And what is %s for? Not for integers of any size.

Herpy Derpy

Except now, this function throws a segmentation fault for strings known to be atleast 8 bytes in size. It does it for the expliccit shifting and the memcpy hack.

#include <stddef.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

void storeLong(char* array, size_t off, int64_t val);

...

void storeLong(char* array, size_t off, int64_t val)
{
/*array[off + 0] = (char)((val & 0xff00000000000000L) >> 56);
array[off + 1] = (char)((val & 0x00ff000000000000L) >> 48);
array[off + 2] = (char)((val & 0x0000ff0000000000L) >> 40);
array[off + 3] = (char)((val & 0x000000ff00000000L) >> 32);
array[off + 4] = (char)((val & 0x00000000ff000000L) >> 24);
array[off + 5] = (char)((val & 0x0000000000ff0000L) >> 16);
array[off + 6] = (char)((val & 0x000000000000ff00L) >> 8);
array[off + 7] = (char)((val & 0x00000000000000ffL));*/


memcpy(array + off, &val, sizeof(int64_t));


}

gnasher729
Jul 24, 2012, 06:56 PM
Herpy Derpy

Except now, this function throws a segmentation fault for strings known to be atleast 8 bytes in size. It does it for the expliccit shifting and the memcpy hack.


You wrote

char* word = "abcdefgh";

In C / C++ / Objective C, a string literal like "abcdefgh" which is not used to initialise an array of char is implemented as a pointer to an unnamed static array of const char. So what you write is exactly the same as

static const char invisible_word [9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0 };
char* word = (char *) &invisible_word [0];

Any attempt to change the chars that word points to will result in a crash.

MorphingDragon
Jul 24, 2012, 08:12 PM
You wrote

char* word = "abcdefgh";In C / C++ / Objective C, a string literal like "abcdefgh" which is not used to initialise an array of char is implemented as a pointer to an unnamed static array of const char. So what you write is exactly the same as

static const char invisible_word [9] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 0 };
char* word = (char *) &invisible_word [0];Any attempt to change the chars that word points to will result in a crash.

Wow I really do remember nothing about C. :o

Cromulent
Aug 2, 2012, 06:42 AM
word = (char*) storeLong(word, 0, num);

...

void storeLong(char* array, size_t off, int64_t val)


You have a bug here. You call storeLong() in your main() function and store the return value in word which you cast to char*. Yet your definition of the storeLong() function states that it returns void (i.e it does not return a value).