(size_t)&(((s *)0)->m)的理解

本文详细解释了offsetof宏的工作原理,说明了如何通过类型强制转换及指针操作计算结构体成员相对于结构体起始位置的偏移量,同时指出该方法不适用于位域成员。

#define offsetof(s,m)   (size_t)&(((s *)0)->m)
 

看了半天没弄懂,空指针怎么会不出错的,他们说没有写入操作,即没有 mov x, dword ptr []。找了下别人的理解,最详细的如下:

((s *)0):强制转化成数据结构指针,并使其指向地址0;
((s *)0)->m:使该指针指向成员m
&(((s *)0)->m):获取该成员m的地址
(size_t)&(((s *)0)->m):转化这个地址为合适的类型
 
你可能会迷惑,这样强制转换后的结构指针怎么可以用来访问结构体字段?呵呵,其实这个表达式根本没有也不打算访问m字段。ANSI C标准允许任何值为0的常量被强制转换成任何一种类型的指针,并且转换结果是一个NULL指针,因此((s*)0)的结果就是一个类型为s*的NULL指针。如果利用这个NULL指针来访问s的成员当然是非法的,但&(((s*)0)->m)的意图并非想存取s字段内容,而仅仅是计算当结构体实例的首址为((s*)0)时m字段的地址。聪明的编译器根本就不生成访问m的代码,而仅仅是根据s的内存布局和结构体实例首址在编译期计算这个(常量)地址,这样就完全避免了通过NULL指针访问内存的问题。又因为首址的值为0,所以这个地址的值就是字段相对于结构体基址的偏移。
 
这里有个地方需要注意:就是offsetof虽然同样适用于union结构,但它不能用于计算位域(bitfield)成员在数据结构中的偏移量。
 
typedef struct
{
  unsigned int a:3;
  unsigned int b:13;
  unsigned int c:16;
}foo;
 
使用offset(foo,a)计算a在foo中的偏移量,编译器会报


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/hzh007hzh/archive/2009/05/29/4224223.aspx

// Allocate memory in large chunks in order to avoid fragmenting the // heap too much. Assume that __n is properly aligned. We hold the // allocation lock. char * __pool_alloc_base::_M_allocate_chunk(size_t __n, int &__nobjs) { char *__result; size_t __total_bytes = __n * __nobjs; size_t __bytes_left = _S_end_free - _S_start_free; if (__bytes_left >= __total_bytes) { __result = _S_start_free; _S_start_free += __total_bytes; return __result; } else if (__bytes_left >= __n) { __nobjs = (int)(__bytes_left / __n); __total_bytes = __n * __nobjs; __result = _S_start_free; _S_start_free += __total_bytes; return __result; } else { // Try to make use of the left-over piece. if (__bytes_left > 0) { _Obj *volatile *__free_list = _M_get_free_list(__bytes_left); ((_Obj *)(void *)_S_start_free)->_M_free_list_link = *__free_list; *__free_list = (_Obj *)(void *)_S_start_free; } size_t __bytes_to_get = (2 * __total_bytes + _M_round_up(_S_heap_size >> 4)); __try { _S_start_free = static_cast(::operator new(__bytes_to_get)); } __catch(const std::bad_alloc &) { // Try to make do with what we have. That can't hurt. We // do not try smaller requests, since that tends to result // in disaster on multi-process machines. size_t __i = __n; for (; __i <= (size_t)_S_max_bytes; __i += (size_t)_S_align) { _Obj *volatile *__free_list = _M_get_free_list(__i); _Obj *__p = *__free_list; if (__p != 0) { *__free_list = __p->_M_free_list_link; _S_start_free = (char *)__p; _S_end_free = _S_start_free + __i; return _M_allocate_chunk(__n, __nobjs); // Any leftover piece will eventually make it to the // right free list. } } // What we have wasn't enough. Rethrow. _S_start_free = _S_end_free = 0; // We have no chunk. __throw_exception_again; } _S_heap_size += __bytes_to_get; _S_end_free = _S_start_free + __bytes_to_get; return _M_allocate_chunk(__n, __nobjs); } } 详细解释这个函数,能画图和动画演示么
最新发布
09-04
``` clc; clear; close all; % 参数设置 M = 1024; N = 1024; file = '1.mat'; % 输入你的全息图 data = load(file); fn = fieldnames(data); holo= double(data.(fn{1})); holo_amp = sqrt(holo / max(holo(:))); % 归一化幅值 amp_gt = im2double(imread('BJUT.png'));% 原始复振幅的“幅值图” amp_gt = imresize(amp_gt, [1024, 1024]); amp_gt = rgb2gray(amp_gt); amp_gt = amp_gt / max(amp_gt(:));%归一化幅值 lambda = 532e-9; % 波长 dx = 2.9e-6; % 像素尺寸 z = 17e-3; % 传播距离 N_iter = 100; % 迭代次数 % 相位复原 [U_obj, recon_amp, recon_phase] = phase_recovery(holo_amp, lambda, dx, z, N_iter, amp_gt); % 显示结果 figure; subplot(1,2,1); imshow(recon_amp, []); title('复原幅值'); subplot(1,2,2); imshow(recon_phase, []); title('复原相位'); % 评估指标 recon_amp_norm = recon_amp / max(recon_amp(:)); mse = mean((amp_gt(:) - recon_amp_norm(:)).^2); rmse_val = sqrt(mse); psnr_val = 10 * log10(1 / mse); fprintf('[评估结果] PSNR = %.2f dB,RMSE = %.4f\n', psnr_val, rmse_val); %% === 角谱传播函数 === function U_out = angular_spectrum(U_in, z, wavelength, dx) [M, N] = size(U_in); k = 2 * pi / wavelength; fx = (-N/2:N/2-1) / (N * dx); fy = (-M/2:M/2-1) / (M * dx); [FX, FY] = meshgrid(fx, fy); H = exp(1j * k * z * sqrt(1 - (wavelength * FX).^2 - (wavelength * FY).^2)); H((wavelength * FX).^2 + (wavelength * FY).^2 > 1) = 0; U_out = ifftshift(ifft2(fft2(fftshift(U_in)) .* fftshift(H))); end %% === 相位复原主函数 === function [U_obj, recon_amp, recon_phase] = phase_recovery(holo_amp, wavelength, dx, z, num_iter, amp_gt) [M, N] = size(holo_amp); H = holo_amp; % 初始记录面幅值 phase_est = zeros(M, N); % 初始相位设为 0 U_rec = H .* exp(1j * phase_est); % 初始复振幅 for iter = 1:num_iter U_obj = angular_spectrum(U_rec, -z, wavelength, dx); % 传播到物面 A = abs(U_obj); phi = angle(U_obj); A = min(A, 1); % 正吸收约束 U_obj = A .* exp(1j * phi); % TV 去噪(Split Bregman) U_obj = TV_denoise(U_obj, 0.02, 5); % 可调参数 % 传播回记录面并施加幅值约束 U_rec = angular_spectrum(U_obj, z, wavelength, dx); U_rec = H .* exp(1j * angle(U_rec)); % 可视化中间迭代 if mod(iter, 20) == 0 figure(2); imshow(abs(U_obj), []); title(['Iter ' num2str(iter)]); drawnow; end end % 最后再传播一次获得最终复原图 U_obj = angular_spectrum(U_rec, -z, wavelength, dx); recon_amp = abs(U_obj); recon_phase = angle(U_obj); end %% === Split Bregman TV 去噪 % === function U_out = TV_denoise(U_in, lambda, iter_tv)%lambda:TV正则项系数 [m, n] = size(U_in);%初始化 U_out = U_in; dx = zeros(m, n); dy = zeros(m, n); bx = zeros(m, n); by = zeros(m, n); mu = 1; for k = 1:iter_tv [Ux, Uy] = gradient(U_out);%计算梯度项 dx = shrink(Ux + bx, lambda / mu);%更新 d(软阈值) dy = shrink(Uy + by, lambda / mu); div_d_b = divergence(dx - bx, dy - by);%更新 U(解一个波动方程) U_out = solve_poisson(U_in + mu * div_d_b, mu); [Ux, Uy] = gradient(U_out);%更新 Bregman 参数 bx = bx + (Ux - dx); by = by + (Uy - dy); end end function out = shrink(x, t)%软阈值函数,适用于复数 out = max(abs(x) - t, 0) ./ (abs(x) + 1e-8) .* x; end function div = divergence(px, py)%计算散度 [m, n] = size(px); div = zeros(m, n); div(:,1:end-1) = px(:,1:end-1) - px(:,2:end); div(:,end) = px(:,end); div(1:end-1,:) = div(1:end-1,:) + py(1:end-1,:) - py(2:end,:); div(end,:) = div(end,:) + py(end,:); end function U = solve_poisson(rhs, mu)%使用频域方法解泊松方程 [m, n] = size(rhs); [fx, fy] = meshgrid(0:n-1, 0:m-1); fx = fx / n; fy = fy / m; denom = 1 + mu * ((2 - 2 * cos(2 * pi * fx)) + (2 - 2 * cos(2 * pi * fy))); U = real(ifft2(fft2(rhs) ./ denom)); end```请帮忙改善一下这个代码
03-22
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值