- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我在玩 memcpy 时偶然发现了一个奇怪的结果,在 bool memcpy 之后对同一内存指针调用的 memcpy 给出了意想不到的结果。
我创建了一个简单的测试结构,其中包含一堆不同类型的变量。我将结构转换为 unsigned char 指针,然后使用 memcpy 将数据从该指针复制到单独的变量中。我试着绕过 memcpy 的偏移量并将 int memcpy 移到 bool 之前(更改了测试结构的布局,以便 int 也位于 bool 之前)。令人惊讶的是,转移解决了问题。
// Simple struct containing 3 floats
struct vector
{
float x;
float y;
float z;
};
// My test struct
struct test2
{
float a;
vector b;
bool c;
int d;
};
int chính()
{
// I create my structure on the heap here and assign values
test2* test2ptr = new test2();
test2ptr->a = 50;
test2ptr->b.x = 100;
test2ptr->b.y = 101;
test2ptr->b.z = 102;
test2ptr->c = true;
test2ptr->d = 5;
// Then turn the struct into an array of single bytes
unsigned char* data = (unsigned char*)test2ptr;
// Variable for keeping track of the offset
unsigned int offset = 0;
// Variables that I want the memory copied into they
float a;
vector b;
bool c;
int d;
// I copy the memory here in the same order as it is defined in the struct
std::memcpy(&a, data, sizeof(float));
// Add the copied data size in bytes to the offset
offset += sizeof(float);
std::memcpy(&b, data + offset, sizeof(vector));
offset += sizeof(vector);
std::memcpy(&c, data + offset, sizeof(bool));
offset += sizeof(bool);
// It all works until here the results are the same as the ones I assigned
// however the int value becomes 83886080 instead of 5
// moving this above the bool memcpy (and moving the variable in the struct too) fixes the problem
std::memcpy(&d, data + offset, sizeof(int));
offset += sizeof(int);
trả về 0;
}
所以我预计 d 的值为 5,但它变成了 83886080,我认为这只是随机未初始化的内存。
câu trả lời hay nhất
您忽略了结构中数据的填充。
看看下面的简化示例:
struct X
{
bool b;
số nguyên i;
};
int chính()
{
X x;
std::cout << "Address of b " << (void*)(&x.b) << std::endl;
std::cout << "Address of i " << (void*)(&x.i) << std::endl;
}
这在我的电脑上的结果是:
Address of b 0x7ffce023f548
Address of i 0x7ffce023f54c
如您所见,结构中的 bool
值在这里占用 4 个字节,即使它在其内容中使用的更少。编译器必须向结构添加填充字节,以使 cpu 可以直接访问数据。如果您将数据按照代码中的写入方式进行线性排列,则编译器必须针对所有访问生成汇编指令,以便稍后对齐数据,这会大大降低您的程序速度。
您可以通过添加 pragma pack
或与您的编译器类似的东西来强制编译器这样做。所有的 pragma
都是特定于编译器的!
对于您的程序,如果 memcpy
的数据不是您要访问的元素之前的数据元素的大小,则必须使用地址,因为这会忽略填充字节。
如果我在我的程序之前添加一个pragma pack(1)
,输出是:
Address of b 0x7ffd16c79cfb
Address of i 0x7ffd16c79cfc
如您所见,bool 和 int 之间不再有填充字节。但是后面访问 i 的代码会很大很慢!所以完全避免使用 #pragma pack
!
关于c++ - 为什么调用 memcpy 到 bool 值后 memcpy 到 int 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56584353/
Để mã của tôi được viết gần như hoàn toàn bằng Jquery, tôi muốn viết lại các lệnh gọi AJAX trong Jquery. Đây là lệnh gọi từ trang web tới servlet Tomcat. Mã tương tự cho tình huống hiện tại của tôi: var http = new
Tôi muốn gọi hàm C từ Java bằng JNI. Trong hàm C, tôi muốn tạo một JVM và gọi một số đối tượng Java. Khi tôi cố gắng tạo một JVM, JNI_CreateJavaVM trả về -1. Vì vậy, tôi muốn biết
Nhìn xung quanh, tôi thấy rằng cách tốt nhất để gọi một hàm Javascript từ HTML là đặt chính hàm đó vào HTML, thay vì một tệp Javascript bên ngoài. Vì vậy, tôi đã tìm kiếm trên mạng và tìm thấy một số hướng dẫn ngắn để tôi có thể root
Tôi có thành phần này: nhập {Component} từ 'angular2/core'; nhập {UserServices} từ '../services/UserService
Tôi đang cố gắng triển khai mô hình máy khách/máy chủ OpenSSL đơn giản trong C và tò mò về việc sử dụng các lệnh gọi BIO_*, cho phép một số chức năng hay so với các lệnh gọi SSL_* thô. Tôi còn khá mới với điều này nên tôi có thể sai hoàn toàn
Tôi đang xử lý một vấn đề khó khăn liên quan đến lệnh gọi không đồng bộ: hàm JQuery thực thi khi người dùng nhấp vào rồi gọi tệp php để kiểm tra xem dữ liệu đầu vào của người dùng có trùng lặp với thông tin đã có trong cơ sở dữ liệu hay không. Nếu vậy, người dùng sẽ được nhắc xác nhận xem họ muốn tiếp tục hay hủy nếu nhấp vào
Tôi có lớp sau. Nhiệm vụ công khai { Nhiệm vụ tĩnh công khai getInstance(String taskName) { trả về mới
Này, tôi đang xây dựng một trò chơi nhỏ và tôi đang tạo các cấp độ bằng cách tạo một vectơ số liên kết với 1-4 màu thông qua một bảng liệt kê. Vấn đề là vòng lặp (trong Simon::loadChallenge) tôi sẽ
Tôi có api khởi động mùa xuân java (bộ thu dữ liệu) được khách hàng gọi để lưu một số dữ liệu. Sau khi hoàn tất việc lưu giữ dữ liệu, tôi muốn thực hiện một lệnh gọi api khác (sẽ xử lý dữ liệu đã lưu - trình tổng hợp dữ liệu) để tự phân biệt
Đầu tiên, điều này liên quan đến ứng dụng máy tính để bàn chứ không phải ứng dụng ASP .Net. Tôi đã thêm tham chiếu Web vào dự án của mình và xây dựng nhiều đối tượng dữ liệu khác nhau như PayerInfo, Địa chỉ và Thẻ tín dụng. Nhưng vấn đề
Làm cách nào để yêu cầu FAKE biên dịch tệp .fs bằng fsc? Điểm thưởng khi giải thích cách chuyển các đối số như -a và -target:dll. EDIT: Tôi nên làm rõ rằng tôi đang cố gắng thực hiện việc này mà không cần MSBuild/xbuild/. sl
Tôi đã định cấu hình một mô hình đường trục đơn giản và xem bằng cách sử dụng mẫu gạch dưới. Hai API riêng biệt sử dụng cấu hình giống hệt nhau. API 1 hoạt động như mong đợi. Để tái hiện sự cố, hãy nhận xét URL cho API 1 và bỏ ghi chú URL cho API 2
Tôi không chắc đâu sẽ là cách tiếp cận tốt hơn hay cách tiếp cận thực tế hơn. Tôi đang tìm cách tạo một hệ thống thư mục từ đầu nhưng không chắc chắn cách tiếp cận tốt nhất là gì. Tôi nghĩ rằng tôi sử dụng các đối tượng khi cần hiển thị thông tin, ví dụ info.php?id=100. Có mã như thế này để hiển thị Game.cl
từ datetime nhập timedelta lớp A: def __abs__(self): return -self lớp B1(A):
Tôi gặp sự cố khi thao tác với các mảng trong mã mẫu Trò chơi cuộc sống này. Tình huống: "Trò chơi cuộc sống" là một công nghệ tự động hóa tế bào được phát minh bởi John Conway. Nó bao gồm một mạng lưới các tế bào sống/chết/sinh sản theo các quy luật toán học. Các ô sống và chết trong lưới này
Nếu tôi gọi read() như thế này để đọc một tệp: unsigned char buf[512]; memset(buf, 0, sizeof(unsigned char) * 512);
Tôi đã viết một máy chủ đơn giản bằng C và muốn gọi nó với chức năng tương tự như gọi các daemon C khác (chẳng hạn như gọi nó bằng ./ftpd start và tắt phiên bản bằng ./ftpd stop). Rõ ràng vấn đề tôi đang gặp phải là tôi không biết
Trong dos, nó hoạt động khi tôi dán lệnh này: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
Trong dos, nó hoạt động khi tôi dán lệnh này: "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" https://google.
Tôi muốn có thể gọi python3 từ cmd trên máy tính Windows 10 của mình. Tôi đã cài đặt lại Python3.7 và đảm bảo đã chọn tùy chọn "Thêm vào đường dẫn", nhưng vẫn không thể gọi python3 và nhận CMD để khởi động P
Tôi là một lập trình viên xuất sắc, rất giỏi!