#651 c const

2021-10-06

C 常量

c 常量的两种实现方法:

  1. define
  2. const 关键字

const 关键字

  • 常量 const int a / int const a
    a 是一个 int 类型常量
  • 常量指针 const int *a / int const *a
    a 是一个指针,指向一个 int 类型常量
  • 指针常量 int *const a
    a 是一个指针常量(指针类型(int *)的常量), 指向的位置不能修改
  • 指向常量的指针常量 const int *const a
    同上,不过更进一步,指向位置是一个常量(const int),不能更改

问题

int main()
{
    const int a = 1;

    int *ptr = (int *)&a;
    *ptr = 2;
    printf("a = %d\n", a);

    return 0;
}

如果用 gcc 编译会输出:a = 2, g++ 的话,会输出 a = 1, WHY? 为什么 C 允许修改常量,是不是一个 BUG?

原因

参考网上诸多资料,我的理解如下:

  1. C 会给 const 常量正常分配内存,const 只会在编译时起到静态分析的作用(限定常量不能作为左值)。
  2. C++ 则是将 const 常量放在符号表,如果用指针指向这个常量,会新分配内存地址,操作也是操作的这个内存空间,符号表中存储的值不受影响。
  3. 符号表在内存布局中的那一部分?

参考资料与拓展阅读

#649 scrypt 加密

2021-10-03

在 Python 标准库 hashlib 中见过 scrypt,说是 3.6 引入。
然后,这两天看到的资讯说是 Django 4 将加入了 scrypt 做密码哈希,据说安全性比之前的 PBKDF2 更好。
PS: 由于需要 OpenSSL 1.1+ 的支持,以及会消耗更多的内存,所以不是默认选项。

#647 Python 内置函数: hash

2021-10-01

一个不值一提的小问题:
有个地方使用 hash 方法来做哈希计算,将字符串转换成一个数值,但是发现改用 Python 3 之后,这个值每次运行都不一样了。

#644 DedeCMS 开始割韭菜了

2021-09-29

织梦官网放出上面这张公告:除了 “个人非盈利” 网站,其他没有拿到正式授权的织梦网站需要交 5800 授权费。

他们可能已经把清单列好了,律师团队也准备好了,正磨刀霍霍向着小站长们。

这可能就是中国特色开源协议的正确使用方式。

PS: 虽然我觉得 织梦CMS 是个垃圾,但我也不知道为啥,据说很多小站都是用的这个系统。

#642 Python 源码学习 11: PyFrameObject

2021-09-25
// Include/cpython/frameobject.h
struct _frame {
    PyObject_VAR_HEAD
    struct _frame *f_back;      /* previous frame, or NULL */
    PyCodeObject *f_code;       /* code segment */
    PyObject *f_builtins;       /* builtin symbol table (PyDictObject) */
    PyObject *f_globals;        /* global symbol table (PyDictObject) */
    PyObject *f_locals;         /* local symbol table (any mapping) */
    PyObject **f_valuestack;    /* points after the last local */
    /* Next free slot in f_valuestack.  Frame creation sets to f_valuestack.
       Frame evaluation usually NULLs it, but a frame that yields sets it
       to the current stack top. */
    PyObject **f_stacktop;
    PyObject *f_trace;          /* Trace function */
    char f_trace_lines;         /* Emit per-line trace events? */
    char f_trace_opcodes;       /* Emit per-opcode trace events? */

    /* Borrowed reference to a generator, or NULL */
    PyObject *f_gen;

    int f_lasti;                /* Last instruction if called */
    /* Call PyFrame_GetLineNumber() instead of reading this field
       directly.  As of 2.3 f_lineno is only valid when tracing is
       active (i.e. when f_trace is set).  At other times we use
       PyCode_Addr2Line to calculate the line from the current
       bytecode index. */
    int f_lineno;               /* Current line number */
    int f_iblock;               /* index in f_blockstack */
    char f_executing;           /* whether the frame is still executing */
    PyTryBlock f_blockstack[CO_MAXBLOCKS]; /* for try and loop blocks */
    PyObject *f_localsplus[1];  /* locals+stack, dynamically sized */
};

// Include/pyframe.h
typedef struct _frame PyFrameObject;

字节码

def sum(a, b):
    return a + b

def test():
    print('hello world')
    print(sum(1, 2))

import dis
dis.dis(sum)
dis.dis(test)
2           0 LOAD_FAST                0 (a)
            2 LOAD_FAST                1 (b)
            4 BINARY_ADD
            6 RETURN_VALUE
5           0 LOAD_GLOBAL              0 (print)
            2 LOAD_CONST               1 ('hello world')
            4 CALL_FUNCTION            1
            6 POP_TOP

6           8 LOAD_GLOBAL              0 (print)
           10 LOAD_GLOBAL              1 (sum)
           12 LOAD_CONST               2 (1)
           14 LOAD_CONST               3 (2)
           16 CALL_FUNCTION            2
           18 CALL_FUNCTION            1
           20 POP_TOP
           22 LOAD_CONST               0 (None)
           24 RETURN_VALUE

行号,指令偏移,指令,参数,参数值(参考)

查看字节码:

sum.__code__.co_code
sum.__code__.co_varnames
sum.__code__.co_consts
sum.__code__.co_names

参考资料与拓展阅读