指针

指针

内存和地址

       对于一个占用4个字节的int型数据,它有一个地址,至于它的地址是它最左边还是最右边的那个字节的位置,不同的机器有不同的规定

       还有一个比较蛋疼的边界对齐boundary alignment,就是要求对其的机器上,整型值存储的起始位置只能是某些特定的字节,通常是24的倍数。这也导致了有些数组的内存浪费。

       对于名字和内存位置之间的关联并不是硬件提供的,而是由编译器为我们实现的。

值和类型

       不管是int数、float数还是double型的数据,存储在计算机上的全是0或者1。所以对该数值的解析就决定了它的结果。比如下例:

一个二进制数为0110 0111 0110 1100 0110 1111 0110 0010

解析为:

类型

132int

1735159650

216int

2647628514

4个字符

glob

浮点数

1.116533X1024

机器指令

beg.+110ble.+102

       所以对于相同的数据,不同的解析方式决定了它的结果。

指针变量的内容

int *d=&a;的含义为da的地址,可以分解为int *d; d = &a;千万不要理解成了da的值。

未初始化和非法的指针

       未初始化的指针极具危险。指针必须初始化方可使用。

NULL指针

       标准定义了NULL指针,它作为一个特殊的指针变量,表示不指向任何东西。要使一个指针变量为NULL,你可以给它赋一个零值。

指针、间接访问和左值

       指针变量可以作为左值,并不是因为它们是指针,而是因为它们是变量。比如*a = 10 – *a

指针常量

       假设int a的地址为100,那么*100 = 25;代表的意思貌似是将25赋值给a,因为a是位置100所存储的变量,但是这个语句是错 的。这个语句是非法的,因为字面值100的类型是整型,而间接访问操作只能作用于指针类型表达式。所以,如果确实希望实现上面貌似代表的含义,需要使用强制类型转换,即*(int *)100 = 25

指针运算

       指针加法的 在于可以自动调整跳过的字节数,比如+1,对于char1个字节,而int4个字节,double可能就是8个字节。

关系运算

       只用当两个指针都指向同一个数组中的元素时,才允许从一个指针减去另一个指针。

       指针运算只有作用于数组中其结果才是可以预测的。对任何并非指向数组元素的指针执行算术运算是非法的(但常常很难被检测到)。

总结

l  大多数编译器都不会检查指针表达式的结果是否位于合法的边界之内。因此,程序员应该负起责任;

l  不要对一个为初始化的指针变量进行解引用;

l  不要对一个NULL指针进行解引用。

python object notes

Python对象

python对象具有三个特性:身份(id)、类型(type)、值。

三特性在对象创建时被赋值。只有值可以改变,其他只读。

类型本身也是对象。

 

python之内建函数type()

示例程序:

>>> type(2) # 2的类型为int

<type ‘int’> 

>>> type(s) # s为一个类的对象

<type ‘instance’>

>>> type(type(5))

<type ‘type’> # type5)的类型为type

 

<type ‘int’>是一个类型对象,<type ‘type’>是类型对象的类型

 

pythonNull

python有一个特殊的类型,即 Null 对象或者 NoneType,它只有一个值 None.

None的布尔值总是False.

下列对象的布尔值为False.

None

False

所有的值为零的数:

0(整形)

0.0(浮点型)

0L(长整形)

0.0+0.0j(复数)

“”(空字符串)

[](空列表)

()(空元组)

{}(空字典)

 

python之切片对象

sequence[起始索引 : 结束索引 : 步进值]

示例程序:

>>> foostr = ‘12345’

>>> foostr[::-1]

‘54321’

>>> foostr[::1]

‘12345’

>>> foostr[::-2]

‘531’

>>> foostr[::2]

‘135’

>>> 

 

python之对象比较

python提供了 is is not 运算符来测试两个变量是否指向同一个对象。

示例程序:

>>> a = 1.3

>>> b = 1 + 0.3

>>> id(a)

12362032

>>> id(b)

12362000

>>> a is b

False

>>> a is not b

True

>>> 

 

 

内建函数strrepr以及运算符

内建函数str()repr()或反引号操作符()可以方便地以字符串的方式获取对象的内容、类型、数值属性等信息。str()函数得到的字符串可读性好,而repr()函数得到的字符串通常可以用来重新获得该对象,通常情况下obj == eval(repr(obj)) 这个等式是成立的。这两个函数接受一个对象作为其参数,返回适当的字符串。在下面的例子里,我们会随机取一些Python对象来查看他们的字符串表示。

>>> str(4.53-2j)
‘(4.53-2j)’
>>>
>>> str(1)
‘1’
>>>
>>> str(2e10)
‘20000000000.0’
>>>
>>> str([0, 5, 9, 9])
‘[0, 5, 9, 9]’
>>>
>>> repr([0, 5, 9, 9])
‘[0, 5, 9, 9]’
>>>
>>> `[0, 5, 9, 9]`
‘[0, 5, 9, 9]’

尽管str(),repr()运算在特性和功能方面都非常相似,事实上repr()做的是完全一样的事情,它们返回的是一个对象的官方字符串表示,也就是说绝大多数情况下可以通过求值运算(使用内建函数eval())重新得到该对象,但str()则有所不同。str()致力于生成一个对象的可读性好的字符串表示,它的返回结果通常无法用于eval()求值,但很适合用于print语句输出。需要再次提醒的是,并不是所有repr()返回的字符串都能够用 eval()内建函数得到原来的对象。

>>> eval(`type(type))`)
File “<stdin>”, line 1
eval(`type(type))`)

SyntaxError
invalid syntax

也就是说 repr() 输出对 Python比较友好,而str()的输出对用户比较友好。虽然如此,很多情况下这三者的输出仍然都是完全一样的。


核心笔记:为什么我们有了repr()还需要

Python学习过程中,你偶尔会遇到某个操作符和某个函数是做同样一件事情。之所以如此是因为某些场合函数会比操作符更适合使用。举个例子,当处理类似函数这样的可执行对象或根据不同的数据项调用不同的函数处理时,函数就比操作符用起来方便。另一个例子就是双星号(**)乘方运算和pow()内建函数,x ** y pow(x,y) 执行的都是xy
次方

 

 

type()isinstance()

Python不支持方法或函数重载,因此你必须自己保证调用的就是你想要的函数或对象。type()返回任意Python对象的类型,而不局限于标准类型。让我们通过交互式解释器来看几个使用type()内建函数返回多种对象类型的例子。

>>> type(”)
<type ‘str’>
>>>
>>> s = ‘xyz’
>>> type(s)
<type ‘str’>
>>>
>>> type(100)
<type ‘int’>
>>> type(0+0j)
<type ‘complex’>
>>> type(0L)
<type ‘long’>
>>> type(0.0)
<type ‘float’>
>>>
>>> type([])
<type ‘list’>
>>> type(())
<type ‘tuple’>
>>> type({})
<type ‘dict’>
>>> type(type)
<type ‘type’>
>>>
>>> class Foo: pass        # new-style class

>>> foo = Foo()
>>> class Bar(object): pass      # new-style class

>>> bar = Bar()
>>>

>>> type(Foo)
<type ‘classobj’>
>>> type(foo)
<type ‘instance’>
>>> type(Bar)
<type ‘type’>
>>> type(bar)
<class ‘__main__.Bar’>

Python2.2统一了类型和类,如果你使用的是低于Python2.2的解释器,你可能看到不一样的输出结果。

 >>> type(”)
<type ‘string’>
>>> type(0L)
<type ‘long int’>
>>> type({})
<type ‘dictionary’>
>>> type(type)
<type ‘builtin_function_or_method’>
>>>
>>> type(Foo)    # assumes Foo created as in above
<type ‘class’>
>>> type(foo)    # assumes foo instantiated also
<type ‘instance’>

除了内建函数type(),还有一个有用的内建函数叫做 isinstance()

 

Python类型操作符和内建函数总结

下表列出了所有操作符和内建函数,其中操作符顺序是按优先级从高到低排列的。同一种灰度的操作符拥有同样的优先级。注意在operator模块中有这些(和绝大多数Python)操作符相应的同功能的函数可供使用。

标准类型操作符和内建函数

操作符/函数

   

    a

字符串表示

对象的字符串表示

str

内建函数

cmp(obj1, obj2)

比较两个对象

int

repr(obj)

对象的字符串表示

str

str(obj)

对象的字符串表示

str

type(obj)

检测对象的类型

type

值比较

<

小于

bool

>

大于

bool

<=

小于或等于

bool

>=

大于或等于

bool

==

等于

bool

!=

不等于

bool

<>

不等于

bool

对象比较

is

bool

is not

不是

bool

布尔操作符

not

逻辑反

bool

and

逻辑与

bool

or

逻辑或

bool

基本内建数据对象原始类型

我们也许会称它们是Python基本内建数据对象原始类型

l  基本是指这些类型都是Python提供的标准或核心类型。

l  内建是由于这些类型是Python默认就提供的。

l  数据是因为他们用于一般数据存储。

l  对象是因为对象是数据和功能的默认抽象。

l  原始是因为这些类型提供的是最底层的粒度数据存储。

l  类型是因为他们就是数据类型。

不支持的类型

1charbyte

Python没有 char byte 类型来保存单一字符或8位整型。你可以使用长度为1的字符串表示字符或8位整型。

2.指针

Python替你管理内存,因此没有必要访问指针。在Python中你可以使用id()函数得到一个对象的身份号,这是最接近于指针的地址。因为你不能控制这个值,所以其实没有太大意义。其实在Python中,一切都是指针。

3int vs short vs long

Python 的普通整型相当于标准整型类型,不需要类似C语言中的 intshortlong 这三种整型类型。事实上Python的整型实现等同于C语言的长整型。由于Python的整型与长整型密切融合,用户几乎不需要担心什么。你仅需要使用一种类型,就是Python的整型。即便数值超出整型的表达范围,比如两个很大的数相乘,Python会自动的返回一个长整型给你而不会报错。

4float vs double

C语言有单精度和双精度两种浮点类型。Python 的浮点类型实际上是C语言的双精度浮点类型。Python认为同时支持两种浮点类型的好处与支持两种浮点类型带来的开销不成比例,所以Python 决定不支持单精度浮点型。对那些宁愿放弃更大的取值范围而需要更高精确度的用户来说,Python 还有一种十进制浮点型类型 Decimal,不过你必须导入decimal模块才可以使用它。浮点型总是不精确的。Decimals则拥有任意的精度。在处理金钱这类确定的值时,Decimal类型就很有用。在处理重量、长度或其他度量单位的场合,float足够用了。

 

glib data type

Glib数据类型

       Glib提供了自己的一组在GTK+GNOME开发中使用的替代标准C数据类型的数据类型。这样做的原因不仅是便于阅读和使用,而且还便于移植。不管在何种平台上编译应用程序,许多平台对数据的尺寸和运算都会具有许多相同的限制。Glib数据类型保证不管什么样的系统和平台,都是相同的大小。

       Glib的数据类型

数据类型

说明

gboolean

真假或开关的值,一般与Glib定义的TRUEFALSE常量使用

gpointer

对应与void *,但是可读性更强

gcharguchar

对应一个字符和一个无符号字符

gintguintgshort

取代标准c的相应类型

glonggulong

长度根据硬件和操作系统体系结构的不同而变化

gint8guint8gint16

guint16gint32guint32

gint64guint64

具有已知长度的有符号和无符号整数数据类型。对于64位有符号和无符号整数值,仅在范围有限的机器上支持

gfloatgdouble

取代c语言提供的floatdouble

gsize

用来保存数据结构和数据类型尺寸的无符号数据类型

gssize

用来保存数据结构和数据类型尺寸的有符号数据类型

       上述这些类型,可以保证一致性和可读性。不管编译应用程序的平台是什么,定义一组具有可保证长度的数据类型将是一种很好的想法,同时笔记guchar减少了击键次数(unsigned char)。

       测试了一下每种数据类型所占的字节数:

#include <glib.h>
gint main(gint argc,gchar *argv[])
{
    g_print("The length of gboolean is %dn",sizeof(gboolean));
    g_print("The length of gpointer is %dn",sizeof(gpointer));
    g_print("The length of gchar    is %dn",sizeof(gchar));
    g_print("The length of guchar   is %dn",sizeof(guchar));
    g_print("The length of gint     is %dn",sizeof(gint));
    g_print("The length of guint    is %dn",sizeof(guint));
    g_print("The length of gshort   is %dn",sizeof(gshort));
    g_print("The length of glong    is %dn",sizeof(glong));
    g_print("The length of gulong   is %dn",sizeof(gulong));
    g_print("The length of gint8    is %dn",sizeof(gint8));
    g_print("The length of guint8   is %dn",sizeof(guint8));
    g_print("The length of gint16   is %dn",sizeof(gint16));
    g_print("The length of guint16  is %dn",sizeof(guint16));
    g_print("The length of gint32   is %dn",sizeof(gint32));
    g_print("The length of guint32  is %dn",sizeof(guint32));
    g_print("The length of gint64   is %dn",sizeof(gint64));
    g_print("The length of guint64  is %dn",sizeof(guint64));
    g_print("The length of gfloat   is %dn",sizeof(gfloat));
    g_print("The length of gdouble  is %dn",sizeof(gdouble));
    g_print("The length of gsize    is %dn",sizeof(gsize));
    g_print("The length of gssize   is %dn",sizeof(gssize));
    return 0;
}

clip_image002