我在Windows下写了一个程序,然后放到Linux上编译时,出现了很奇怪的提示,遂将问题代码抽离出来,发现原因在于:std::size_t在Linux下是8字节,在Windows下是4字节。当参数为引用时容易出错。
抽离后的代码如下所示:
#include <iostream>
#include <string>
#include <cstdint>//cstdint standard header, uint32_t, int32_t,
#include <cassert>//cassert standard header,
#include <memory>//std::shared_ptr,
typedef std::shared_ptr<std::string> StdStringPtr;
class TestBuffer
{
public:
TestBuffer();
public:
void Feed(const char* data, uint32_t len);
StdStringPtr NextMessage();
private:
static StdStringPtr ParseMessage(const char* buff, uint32_t& posBeg, uint32_t posEnd);
private:
std::string m_buf;
std::size_t m_posBeg;//std::size_t在Linux下是8字节,在Windows下是4字节.
std::size_t m_posEnd;
};
TestBuffer::TestBuffer() :m_posBeg(0), m_posEnd(0){}
void TestBuffer::Feed(const char* data, uint32_t len)
{
m_buf.append(data, len);
m_posEnd += len;
}
StdStringPtr TestBuffer::NextMessage()
{
StdStringPtr msg = TestBuffer::ParseMessage(m_buf.c_str(), m_posBeg, m_posEnd);
assert(m_posBeg <= m_posEnd);
return msg;
}
StdStringPtr TestBuffer::ParseMessage(const char* buff, uint32_t& posBeg, uint32_t posEnd)
{
StdStringPtr msg = nullptr;
const uint32_t msgLen = 5;
//随便写一个实现:5个字符作为一个消息.
if (msgLen <= posEnd - posBeg)
{
msg = std::make_shared<std::string>(buff + posBeg, msgLen);
posBeg += msgLen;
}
return msg;
}
int main()
{
std::printf("sizeof(uint32_t) =%d\n", sizeof(uint32_t));
std::printf("sizeof(uint64_t) =%d\n", sizeof(uint64_t));
std::printf("sizeof(std::size_t)=%d\n", sizeof(std::size_t));
std::string str = "abcde12345ABCDE67890";
TestBuffer myBuf;
myBuf.Feed(str.c_str(), str.length());
StdStringPtr msg;
while ((msg = myBuf.NextMessage()).get() != nullptr)
std::cout << (*msg) << std::endl;
std::cout << "WILL EXIT..." << std::endl;
return 0;
}
在Linux下编译时报错:
[root@localhost ~]# g++ -std=c++11 test.cpp
test.cpp: In member function ‘StdStringPtr TestBuffer::NextMessage()’:
test.cpp:33:82: error: no matching function for call to ‘TestBuffer::ParseMessage(const char*, std::size_t&, std::size_t&)’
StdStringPtr msg = TestBuffer::ParseMessage(m_buf.c_str(), m_posBeg, m_posEnd);
^
test.cpp:33:82: note: candidate is:
test.cpp:16:25: note: static StdStringPtr TestBuffer::ParseMessage(const char*, uint32_t&, uint32_t)
static StdStringPtr ParseMessage(const char* buff, uint32_t& posBeg, uint32_t posEnd);
^
test.cpp:16:25: note: no known conversion for argument 2 from ‘std::size_t {aka long unsigned int}’ to ‘uint32_t& {aka unsigned int&}’
[root@localhost ~]#
刚看到错误提示时,发现函数声明变成‘TestBuffer::ParseMessage(const char*, std::size_t&, std::size_t&)’了,但是我的函数明明是'TestBuffer::ParseMessage(const char* buff, uint32_t& posBeg, uint32_t posEnd)'呀,当时让人感觉太奇怪了。
总结:以后变量的定义、类的数据成员的定义、 函数的定义、等接口性质的地方,一律#include <cstdint>,然后用int32_t、uint32_t、int64_t、uint64_t、等不会有歧义的类型。对于std::size_t类型,已经在std里面了,我原以为它不会有歧义了,没想到随着平台的不同,它还是有改变。