1

我正在尝试使用以下一些简单的代码将一些整数插入到 Postgres 表中。

#include <libpq-fe.h>
#include <stdio.h>
#include <stdint.h>

int main() {
  int64_t i = 0;
  PGconn * connection = PQconnectdb( "dbname='babyfood'" );
  if( !connection || PQstatus( connection ) != CONNECTION_OK )
    return 1;
  printf( "Number: " );
  scanf( "%d", &i );

  char * params[1];
  int param_lengths[1];
  int param_formats[1];
  param_lengths[0] = sizeof( i );
  param_formats[0] = 1;
  params[0] = (char*)&i;
  PGresult * res =  PQexecParams( connection, 
                                  "INSERT INTO intlist VALUES ( $1::int8 )",
                                  1,
                                  NULL,
                                  params,
                                  param_lengths,
                                  param_formats,
                                  0 );
  printf( "%s\n", PQresultErrorMessage( res ) );
  PQclear( res );
  PQfinish( connection );
  return 0;
}

我得到以下结果:

数字: 55
错误:整数超出范围
数字: 1
错误:整数超出范围

我很确定 int64_t 在任何健全的平台上总是适合 8 字节整数。我究竟做错了什么?

4

3 回答 3

3

代替:

params[0] = (char*)&i;

你应该使用:

#include <endian.h>
/* ... */
int64_t const i_big_endian = htobe64(i);
params[0] = (char*)&i_big_endian;

一个htobe64函数将在 little-endian 上切换 endianness,而在 big-endian 上什么也不做。

放弃你的flip_endian功能,因为它会使你的程序与大端/双端计算机不兼容,如 PowerPC、Alpha、摩托罗拉、SPARC、IA64 等。即使你的程序不希望在它们上运行,它也是一种糟糕的风格,速度慢且容易出错。

于 2009-08-20T07:55:56.743 回答
1

好吧,这似乎是一个字节序问题,但仍然不能完全解释它,因为小字节序(即 x86)64 位有符号整数应该适合大字节序 64 位整数,反之亦然,他们只是被破坏。然而,在整数上交换字节序会产生正确的值。交换是通过以下函数完成的:

int64_t flip_endian( int64_t endi ) {
  char* bytearray;
  char swap;
  int64_t orig = endi;
  int i;

  bytearray = (char*)&orig;

  for( i = 0; i < sizeof( orig )/2; ++i ) {
    swap = bytearray[i];
    bytearray[i] = bytearray[ sizeof( orig ) - i - 1 ];
    bytearray[ sizeof( orig ) - i - 1 ] = swap;
  }

  return orig;

}
于 2009-08-19T21:00:34.220 回答
-1

我认为它被作为 32 位 int 传递,然后被转换为 64 位,因为你没有告诉 libpq 格式是什么。

尝试为 paramTypes 指定一个数组,参数为 int8(即 20)的 oid。

于 2009-08-19T20:57:24.930 回答